Git Cheatsheet: Commands, Tips and Tricks 📝#
This is compilation of useful git commands, tips and tricks I created for myself since I kept forgetting some commands related to configuring, searching and managing git repositories. The format is simple, just a list with short descriptions for some common, and other less common, commands which I often find myself looking up online.
For those looking for a more beginner friendly introduction to git, I’ve written one in a previous blog post. Feedback via social media or email is always welcome. You can subscribe to my newsletter by entering your email on the sidebar if you are interested in receiving updates whenever I write something new.
Stay in touch by entering your email below and receive updates whenever I post something new:
As always, thank you for reading and remember that feedback is welcome and appreciated; you may contact me via email or social media. Let me know if there's anything else you'd like to know, something you'd like to have corrected, translated, added or clarified further.
Addendum#
Once you’re done reading this article, you can continue by having a look at the related content I’ve linked below.
The Git Workflow#
Configuration#
1# show current values for all global configuration parameters
2git config --list --global
3
4# let git automatically correct typos such as "comit" and "pussh."
5git config --global help.autocorrect 1
6
7# set a username globally
8git config --global user.name "username"`
9
10# set an email address globally
11git config --global user.email "email@provider.com"
12
13# always --prune for git fetch and git pull
14git config --global fetch.prune true
15
16# remove the previously set username globally
17git config --global --unset user.name
18
19# color the git console
20git config color.ui true
21
22# set the tool used by git for diffing globally
23git config --global diff.tool mytool
24
25# set the tool used by git for merging globally
26git config --global merge.tool mytool
27
28# remove the previously set configuration value globally
29git config --global --unset myparameter
30
31# allows populating the working directory sparsely, that is,
32# cloning only certain directories from a repository
33git config core.sparseCheckout true
34
35# instruct git to retrieve only some directory in addition to
36# those listed in `.git/info/sparse-checkout
37echo "some/directory/inside/the/repository" >> .git/info/sparse-checkout
38
39# define which whitespace problems git should recognize (any whitespace
40# at the end of a line, mixed spaces or tabs)
41git config --global core.whitespace trailing-space,space-before-tab
42
43# tells Git to detect renames. If set to any boolean value, it will
44# enable basic rename detection. If set to "copies" or "copy", it will
45# detect copies, as well.
46git config --global diff.renames copies
47
48# if set, git diff uses a prefix pair that is different from the standard "a/"
49# and "/b" depending on what is being compared.
50git config --global diff.mnemonicprefix true
51
52# always show a diffstat at the end of a merge
53git config --global merge.stat true
54
55# no CRLF to LF output conversion will be performed
56# especially important in the case of MacOS users
57git config --global core.autocrlf input
58
59# whenever pushing, also push local tags
60git config --global push.followTags true
61
62# show also individual files in untracked directories in status queries
63git config --global status.showUntrackedFiles all
64
65# always decorate the output of git log
66git config --global log.decorate full
67
68# the git stash show command without an option will show the stash in patch form
69git config --global stash.showPatch true
70
71# always set the upstream branch of the current branch as the branch to be
72# pushed to when no refspec is given
73git config --global push.default tracking
74
75# ignore the executable bit of files in the working tree
76git config core.fileMode false
Git .ignore Syntax#
|
match a particular file |
|
match a hidden file |
|
match a directory |
|
match a subdirectory |
|
match all files with a certain extension in a subdirectory |
|
recursively match all files with a certain extension in a subdirectory |
|
match everything |
|
do not match file |
Git Workflow#
Initialize and Clone#
1# initialize a git repository in the current working directory
2git init
3
4# clone a remote repository over https
5git clone https://remote.com/repo.git
6
7# clone a remote repository over ssh
8git clone ssh://git@remote.com:/repo.git
9
10# recursively clone a repository over https
11git clone --recursive https://remote.com/repo.git
12
13# recursively clone a repository over ssh
14git clone --recursive ssh://git@remote.com:/repo.git
Track, Add and Commit#
1# start tracking a file or add its current state to the index
2git add file
3
4# add everything which is tracked and has been changed to the index
5git add -u
6
7# add everything which is untracked or has been changed to the index
8git add .
9
10# commit to local history with a given message
11git commit -m "message"
12
13# add all changes to already tracked files and commit with a given
14# message, non-tracked files are excluded
15git commit -am "message"
16
17# modify the last commit including both new modifications and given message
18git commit --amend -m "message"
19
20# perform a commit with an empty message
21git commit --allow-empty-message -m
Status and Diagnostics#
1git status # show status of the working directory
2git status -s # show short version status
3
4git show HEAD # show commit at the head of current branch
5git show mycommit # show commit with object ID mycommit
6git show HEAD:folder/file # show version of folder/file at HEAD
Checking Out#
1# replace file-name with the latest version from the current branch
2git checkout -- filename
3
4# in case fileorbranch is a file, replace fileorbranch with the latest version
5# of the file on the current branch. In case fileorbranch is a branch, replace
6# the working tree with the head of said branch.
7git checkout fileorbranch
8
9# replace the current working tree with commit 05c5fa
10git checkout 05c5fa
11
12# replace the current working tree with the head of the main branch
13git checkout main
Remotes#
1# show the remote branches and their associated urls
2git remote -v
3
4# adds an https url as remote branch under the name origin
5git remote add -f origin https://remote.com/repo.git
6
7# adds an ssh url as remote branch under the name origin
8git remote add -f origin ssh://git@remote.com:/repo.git
9
10# remove the remote with ID origin
11git remote remove -f origin
12
13# set an https url for the remote with ID origin
14git remote set-url origin https://remote.com/repo.git
15
16# set an ssh url for the remote with ID origin
17git remote set-url origin ssh://git@remote.com:/repo.git
18
19# clean up remote non-existent branches
20git remote prune origin
21
22# set the upstream branch, to which changes will be pushed, to origin/main
23git branch --set-upstream-to=origin/main
24
25# set foo as the tracking branch for origin/bar
26git branch –track foo origin/bar
27
28# update local tracking branches with changes from their respective remote ones
29git fetch
30
31# update local tracking branches and remove local references to
32# non-existent remote branches
33git fetch -p
34
35# delete remote tracking branch origin/branch
36git branch -r -d origin/branch
37
38# update local tracking branches and merge changes with local working directory
39git pull
40
41# given one or more existing commits, apply the change each one introduces,
42# recording a new commit for each. This requires your working tree to be clean
43git cherry-pick commitid
44
45# push HEAD to the upstream url
46git push
47
48# push HEAD to the remote named origin
49git push origin
50
51# push HEAD to the branch main on the remote origin
52git push origin main
53
54# push and set origin main as upstream
55git push -u origin main
56
57# delete previous commits and push your current one
58# WARNING: never use force in repositories from which other have pulled [1]
59# https://stackoverflow.com/a/16702355
60git push --force all origin/main
61
62# a safer option to force-push that will not overwrite work on the remote
63# branch if more commits were added ensuring someone else's work is not overwritten
64git push --force-with-lease
65
66# turn the head of a branch into a commit in the currently checked out branch and merge it
67git merge --squash mybranch
Revert and Reset#
1# figures out the changes introduced by commitid and introduces a new commit undoing them.
2git revert commitid
3
4# does the same but doesn't automatically commit
5git revert -n commitid
6
7# updates the index and the HEAD to match the state of commit id.
8# changes made after this commit are moved to “not yet staged for commit”
9git reset commitid
10
11# sets only the HEAD to commitid
12git reset --soft commitid
13
14# sets the HEAD, index and working directory to commitid
15git reset --hard commitid
16
17# sets the HEAD, index and working directory to origin/main
18git reset --hard origin/main
The Stash#
1# take all changes made to working tree and stash them in a new dangling commit, putting
2# the working tree in a clean state
3# DISCLAIMER: this does not include untracked files
4git stash
5
6# stash everything into a dangling commit, including untracked files
7stash save --include-untracked
8
9git stash push file # push individual or multiple files to the stash
10
11# apply the changes which were last stashed to the current working tree
12git pop
13
14# show the stash of commits
15git stash list
16
17# apply a particular commit in the stash
18git stash apply
19
20# apply the second-to-last commit in the stash
21git stash apply stash@{2}
22
23# drop the second-to-last commit in the stash
24git stash drop stash@{2}
25
26# stash only the changes made to the working directory but keep the index unmodified
27git stash --keep-index
28
29# clear the stash
30git stash clear
Working with Submodules#
1# add a submodule to a repository and clone it
2git submodule add https://domain.com/user/repository.git submodules/repository
3
4# add "ignore = all" to .gitmodules in order to ignore all changes in submodules
5cat <<eof >> .gitmodules
6[submodule "mysubmodule"]
7 path = myrepo
8 url = git@gitlab.com:jdsalaro/myrepo.git
9 ignore = all
10eof
11
12# while in a repository which contains submodules, they can be recursively
13# updated by issuing the following command
14git submodule init
15git submodule update
16
17# this an faster way of updating all submodules
18git submodule update --init --recursive
19
20# clone a repository which contains references to other repositories as submodules
21git clone --recursive
22
23# remove completely a submodule
24submodule='mysubmodule';\
25git submodule deinit $submodule;\
26rm -rf .git/modules/$submodule;\
27git config --remove-section $submodule;\
28git rm --cached $submodule
Searching#
1#list the latest tagged revision which includes a given commit
2git name-rev --name-only commitid
3
4# find the branch containing a given commit
5git branch --contains commitid
6
7# show commits which have been cherry-picked and applied to main already
8git cherry -v main
9
10# look for a regular expression in the log of the repository
11git show :/regex
Other Tips and Tricks#
ls-files and ls-tree#
1# list files contained in the current HEAD or in the head of the
2# main branch respectively
3git ls-tree --full-tree -r HEAD
4git ls-tree -r main --name-only
5git ls-tree -r HEAD --name-only
6
7# list files with a certain extension
8git ls-files '*.rb'
9
10# list ignored files
11git ls-files -i
Diffing#
1# diff two branches
2git diff branch1..branch2
3
4# perform a word-diff instead of a line-diff
5git diff --word-diff
6
7git diff --name-status main..branchname
8git diff --stat --color main..branchname
9git diff > changes.patch
10git apply -v changes.patch
Cleaning#
1# perform a dry run and list untracked files or directories that
2# would be removed without actually doing so
3git clean -n
4
5#remove untracked files from the working tree
6git clean -f
7
8# removes untracked files and directories
9git clean -f -d
10
11# same as above but also removes ignored files
12git clean -f -x -d
13
14# same as above but does so through the entire repo
15git clean -fxd :/
Git log#
1git whatchanged myfile
2git log --after="MMM DD YYYY"
3git log --pretty=oneline
4git log --graph --oneline --decorate --all
5git log --name-status
6
7git log --pretty=oneline --max-count=2
8git log --pretty=oneline --since='5 minutes ago'
9git log --pretty=oneline --until='5 minutes ago'
10git log --pretty=oneline --author=<name>
11git log --pretty=oneline --all
12
13git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
14
15git log --grep regexp1 --and --grep regexp2
16git log --grep regexp1 --grep regexp2
17git grep -e regexp1 --or -e regexp2
Set an SSH key for git access#
1ssh-keygen -t rsa -C "user@server.com"
2cat id_rsa.pub
3
4#remote of the repository must point to ssh url
5git remote set-url origin ssh://git@server.com:/repo.git
6
7#don't forget to upload your public key to the respective server
Now the following can be put inside ~/.ssh/config
.
1host server.com
2 HostName server.com
3 IdentityFile ~/.ssh/id_rsa_server
4 User git
List all dangling commits#
1git fsck --no-reflog | awk '/dangling commit/ {print $3}'
Leave the current commit as the only commit in the repository#
1git checkout --orphan new
2git add -A
3git commit -am "Initial commit"
4git branch -D main
5git branch -m main
Remove a file from the repository#
1git filter-branch -f --prune-empty --index-filter \
2 'git rm --cached -r -q -- . ; git reset -q $GIT_COMMIT -- myfile' -- --all
Set up a Git Repository using Git LFS#
In GitLab, projects you must enable git LFS as described in this HOWTO.
The following initializes, sets up a repository with an already created remote, configures git lfs
for popular extensions and pushes everything as the repository’s initial version.
1git init
2git remote add origin git@domain.com:user/repository.git
3
4git lfs track '*.7zip'
5git lfs track "*.avi"
6git lfs track "*.bak"
7git lfs track "*.bin"
8git lfs track '*.bin'
9git lfs track "*.bk"
10git lfs track "*.bmp"
11git lfs track "*.csv"
12git lfs track "*.dat"
13git lfs track "*.data"
14git lfs track "*.db"
15git lfs track "*.dll"
16git lfs track "*.doc"
17git lfs track "*.docx"
18git lfs track "*.exe"
19git lfs track "*.gif"
20git lfs track '*.gz'
21git lfs track "*.ico"
22git lfs track '*.iso'
23git lfs track "*.jar"
24git lfs track "*.jpg"
25git lfs track "*.list "
26git lfs track "*.mp4"
27git lfs track "*.mpg"
28git lfs track "*.msi"
29git lfs track "*.o"
30git lfs track "*.obj"
31git lfs track "*.odt"
32git lfs track "*.odp"
33git lfs track "*.pcap"
34git lfs track "*.pcapng"
35git lfs track "*.pdf"
36git lfs track "*.pickle"
37git lfs track "*.png"
38git lfs track "*.ppt"
39git lfs track "*.pptx"
40git lfs track "*.pyc"
41git lfs track '*.rar'
42git lfs track "*.tar"
43git lfs track '*.tar.gz'
44git lfs track "*.wmv"
45git lfs track "*.webp"
46git lfs track "*.xcf"
47git lfs track "*.xls"
48git lfs track "*.xlsx"
49git lfs track '*.zip'
50
51git add .
52git commit -m "Initial commit"
53git push -u origin main
Git Worktrees#
git worktree add --track -b local-branch wt-directory remote-branch
git worktree remove wt-directory