Skip to content
On this page


Git is a distributed version control system, popular for keeping code repositories in sync.

git servers

CLI Cheat sheet

git pull

git status

git add .

git commit -m "commit message"

git push

What makes a good commit message

  • Use the imperative mood in the subject line
  • Capitalize the subject line
  • Do not end the subject line with a period
  • Limit the subject line to 50 characters
  • Separate subject from body with a blank line
  • Wrap the body at 72 characters
  • Use the body to explain what and why vs. how
  • Capitalize the subject line



git config --list


If you want to see - what repo something pushes back to - the configured id for a given local repo


git config --list --show-origin

To see what the remote server is set to, use:

git remote -v

Sources that a repository is set up to track or follow.

The origin is the one that the repo will push to / pull from by default.

It is possible to have more than one remote !

Remotes can be called whatever you want.

origin vs upstream

upstream can be useful for tracking a boilerplate source for a project.

git remote add upstream
git remote -v

Update origin

Sometimes projects get checked out using the public url, but then changes are made.

git remote remove origin
git remote add origin

git push --set-upstream origin main

git branch --set-upstream-to=origin/main main
git pull

User Details

*** Please tell me who you are.


git config ""
git config "Your Name"

to set the identity to use when making changes to the current repository. Different repositories may have different accounts associated with them.

If that's not something your work requires, you can also set a single account globally:

git config --global ""
git config --global "Your Name"

On a remote shared sever, it may not be appropriate to set user credentials at the account level. In this case, it is possible to provide your details as part of the commit:

git commit --author="Your Name <>"

If you end up committing as a system user and need to update the last commit message, you can use:

git commit --amend --author="Your Name <>"


use ssh -A to share your local credentials with the machine you connect to.

Then if you register your local machine's public ssh key with a service like Gitlab or Github, you won't have to type your username and password every time you push or pull.


If you think you want to store your password, consider setting up an ssh key with your git server instead.

(Don't do this) to store passwords:

git config --global credential.helper store

These credentials are stored in plaintext. Plaintext is insecure, especially on shared systems. via

$ git config --global credential.helper cache
# Set git to use the credential memory cache

$ git config --global credential.helper 'cache --timeout=3600'
# Set the cache to timeout after one hour (setting is in seconds)

Create New Repository

git init

The default branch on git init is currently set to master. If you want to change it to main, this is a good point to do so.

git checkout -b main
git branch -d master
git branch -a

Confirm the remote server is set to your own repo:

git remote -v

From here you can add different remotes (origins and upstreams) as needed.

(See also server section)

Common Workflows


To see the changes to the repository in reverse chronological order:

git log

To see history for a specific file:

git log --follow -p -- file

To see who has made commits to a repository.

git blame filename

see also:

git bisect

Moving files / directories

Tracking a move with git with:

git mv [src] [destination]

** Important Note **

This may affect the ability to see history of files via log.

currently (2020.12), GitHub is not able to associate the history of a moved file with it's previous location's history:

Resoving a conflict

If you try to pull in changes to a file you've modified locally, Git does not try to do the merge.

Use stash to move local changes to the side while pulling in changes from remote.

git stash

Then to unstash:

git stash pop

Undo add files

Newer versions of git show reminders about these commands when running git status

git reset

Revert local changes

git checkout path/to/file will revert the local changes to path/to/file

Collaborative Commits

git commit -m "Commit title
Commit body

Co-authored-by: First Person <>

Changing a commit message

Ideally, do this before pushing up to a public repo, otherwise it results in a branch merge. This will change the most recent commit:

git commit --amend
Changing a commit message - GitHub Docs

Tag current position

A tag is a bit like a branch, but you don't need to check it out.

git tag -a v1.4 -m 'version 1.4'


Show current branch

git branch --show-current

Show a list of all branches available

git branch --all

Switch to existing branch

git checkout name_of_branch

Creating a branch

Assumes you have already checked out the repository locally. Then:

git checkout -b upstream

Which is shorthand for:

git branch upstream
git checkout upstream

Delete local branch

Once you merge a feature branch back in to main, feel free to remove it. It's a good idea to keep your branch names somewhat clean.

git branch -d <local-branch>

If the branch has been shared publicly, and deleted on the remote repository, but still shows up locally (in the list of remote branches), it can be removed with

git remote prune origin

To preview this action, use

git remote prune origin --dry-run

Setting tracking source

If a new local branch has not been pushed up to the origin, use

git push origin [branch-name]

If you wish to set tracking information for this branch:

git branch --set-upstream-to=<remote>/<branch> main


Allows you to pull in changes from master / different branch.

Use merge if your branch is already pushed.

To merge changes

git merge origin/main
git import changes on master to branch at DuckDuckGo

See also web-ui-api-db/ for a branching strategy on handling changes to a foundation that exists outside of the current repository.

Compare branches

git diff branch1..branch2


Tags are like branches that don't have separate revisions. I believe they can be turned in to branches later?

git tag <tagname>

Creates a local tag

git push origin --tags

to push the tag up to the origin.

Renaming a branch

git branch -m <oldname> <new_name>

If you want to rename the current branch

git branch -m <new_name>

If the current branch is available publicly, you'll need to rename it on the remote repo as well.

# Rename the local branch to the new name
git branch -m <old_name> <new_name>

# Delete the old branch on remote - where <remote> is, for example, origin
git push <remote> --delete <old_name>

# Or shorter way to delete remote branch
git push <remote> :<old_name>

git remote -v
# Push the new branch to remote
git push <remote> <new_name>
# e.g.
git push origin <new_name>

# Reset the upstream branch for the new_name local branch
git push <remote> -u <new_name>


Rename master to main

Check out the repository, then

git branch -m master main
git checkout main
git push -u origin main

git push origin --delete master

This may require updating the HEAD reference on Github directly. For a locally hosted git repository, edit the HEAD file on the server. Then, running the following should work:

git push origin --delete master
git branch -m master main
git push -u origin main

Be sure to update defaults in your git server host:

Branch workflows

There are different ways to use branches.

Preparing a release

When it's time to merge a feature branch to the main branch, a few steps are necessary. Examples include diffing the branches, merging the branches, and creating a pull request in your issue tracker to document the change. Frequently these step are done directly in a web service like Github. Better integration with issue tracker that way. Notification emails are automatically sent to collaborators. However, if you need to do it locally for some reason:

Branch from previous commit

You can create the branch via a hash:

git branch branchname <sha1-of-commit>

Or by using a symbolic reference:

git branch branchname HEAD~3

Pick up branches from a remote repository

TODO: confirm

git pull

should do the trick


Similar to merge, but re-writes the history. Use rebase if your branch is local and hasn't been pushed to origin. However, generally, a merge is just fine!

Never rebase a public branch / master -- makes a mess for others who have it checked out already

git checkout name_of_branch
git rebase master version control - Get changes from master into branch in Git - Stack Overflow Merging vs. Rebasing | Atlassian Git Tutorial

Pushing Changes

When working on a branch, git pull will pull changes from the branch, but git push has some surprising behavior that tries to push changes to all matching branches:

error: failed to push some refs to ''
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. If you did not intend to push that branch, you may want to
hint: specify branches to push or set the 'push.default' configuration variable
hint: to 'simple', 'current' or 'upstream' to push only the current branch.
git config push.default simple # just for the current repository
git config --global push.default simple # globally for your account


A fork is another term for a cloned copy of the repository.


Submodules are remote repositories that are tracked separately, but needed for the local project to work.

Submodles allow for external dependencies to be noted and included.


To get submodules on clone:

git clone --recurse-submodules -j8 git://
cd bar

To pull in submodules for an already checked out repository:

git submodule update --init --recursive
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
hint: If you meant to add a submodule, use:
hint: git submodule add <url> path/to/mod
hint: If you added this path by mistake, you can remove it from the
hint: index with:
hint: git rm --cached path/to/mod
hint: See "git help submodule" for more information.

Add a submodule

git submodule add docs

Remove a submodule

To remove a submodule you need to:

Delete the relevant section from the .gitmodules file.
Stage the .gitmodules changes git add .gitmodules
Delete the relevant section from .git/config.
Run git rm --cached path_to_submodule (no trailing slash).
Run rm -rf .git/modules/path_to_submodule (no trailing slash).
Commit git commit -m "Removed submodule "
Delete the now untracked submodule files rm -rf path_to_submodule

Track a specific branch

Typically a specific version of the submodule is tracked.
git submodule track master at DuckDuckGo
git submodule tracking latest - Stack Overflow
How can I specify a branch/tag when adding a Git submodule? - Stack Overflow

Merging two git repositories

This is also the same scenario as working with an upstream or boilerplate.

If you want to merge project-a into project-b:

cd path/to/project-b
git remote add project-a path/to/project-a
git fetch project-a
git merge --allow-unrelated-histories project-a/master # or whichever branch you want to merge
git remote remove project-a merge separate git repositories at DuckDuckGo How do you merge two Git repositories? - Stack Overflow

Before merging, be sure your incoming repository is in it's new subdirectory, otherwise everything will be merged in at the root level.

cd ~/Downloads/technical mkdir technical

This fails with an error:

git mv * technical

Instead, use the -k option:

git mv -k * technical

git commit -m "moving all items to a sub-directory for easier merging"

cd /c/user
git remote add technical ~/Downloads/technical
git fetch technical
git merge --allow-unrelated-histories technical/master # or whichever branch you want to merge

Might have a merge message here, then:

git remote remove technical

Removed Content

Revert vs Reset

If you need to undo a change from a previous commit, a revert is generally preferred over a reset. Resets can cause problems with other shared instances of the repository.

Reminder: It is possible to revert a previous revert to bring the code back in at a later date. How do you roll back (reset) a Git repository to a particular commit? - Stack Overflow git checkout - How do I revert a Git repository to a previous commit? - Stack Overflow git undo pull request merge at DuckDuckGo git - Undo a merge by pull request? - Stack Overflow git - How to undo merge of master branch? - Stack Overflow "Git undo merge" - How to undo merge in git [Tutorial]

Ignore trivial changes

Ignore changes to a file

git update-index --assume-unchanged path/to/file

Resume tracking again:

git update-index --no-assume-unchanged path/to/file Git - Temporarily ignore trivial changes to files - Stack Overflow

Finding a deleted file in history

Sometimes it's easier to use an interface like gitlab (run it locally) or github to browse the history of the commits to the project.

If you do not know the exact path you may use

git log --all --full-history -- **/thefile.*

If you know the path the file was at, you can do this:

git log --all --full-history -- <path-to-file>

An alternative:

git rev-list -n 1 HEAD -- <file_path>

This should show a list of commits in all branches which touched that file. Then, you can find the version of the file you want, and display it with...

git show <SHA> -- <path-to-file>

Or restore it into your working copy with:

git checkout <SHA>^ -- <path-to-file>

Note the caret symbol (^), which gets the checkout prior to the one identified, because at the moment of <SHA> commit the file is deleted, we need to look at the previous commit to get the deleted file's contents


Remove directory from history

If someone adds a directory with large binary files, it may be useful to remove that directory from the history to avoid having to download the large binary data with every clone of the repo.

git filter-branch --tree-filter "rm -rf node_modules" --prune-empty HEAD
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git gc

echo node_modules/ >> .gitignore
git add .gitignore
git commit -m 'Removing node_modules from git history'

git push origin master --force


Changing a commit message

Clearing a public repo's history

-- Remove the history from 
rm -rf .git

-- recreate the repos from the current content only
git init
git add .
git commit -m "Initial commit"

-- push to the github remote repos ensuring you overwrite history
git remote add origin<YOUR ACCOUNT>/<YOUR REPOS>.git
git push -u --force origin main


In Gitlab, you'll need to explicitly allow "Force push" in the project -> settings -> Repository -> Protected Branches. Set "Allowed to force push" to enabled. Once this action is complete, it's a good idea to set this back to disabled.

GUI Clients

Knowing the command line interface is useful when you only have a terminal to work with (ssh, termux, etc).

However, there are plenty of cases where a full desktop environment is availabe. In that case, no need to limit yourself to the CLI.

VS Code has a lot of useful git utilities built in.

Github Desktop is a nice GUI client. Github Desktop is only available on Mac and Windows.

Clients available for linux are listed here:

Looking at:

sudo pacman -Ss git-cola
# not found

sudo pacman -S gitg