Working with GIT
Git is the trail map for a codebase – when you know a few solid commands you can get yourself out of trouble fast, whether you're deep in a feature branch or cleaning up after an experiment.
This page is a quick reference for the git commands and configs I actually use in the wild. It’s meant to be easily scannable when you’re in the middle of work.
Useful GIT Commands
List all local and remote branches
git branch -a
List all files changed by a specific commit
git show --pretty="" --name-only COMMIT_ID
Aborting a rebase
If the working folder gets messed up while resolving a merge conflict caused by a rebase it is possible to start over by aborting the rebase.
git rebase --abort
Use this as a reset rope when a rebase gets too tangled. It abandons the in‑progress rebase and puts you back where you started.
Delete untracked files and directories
git clean -dn
The more useful arguments for this command are:
-n– preview-f– actually deletes-d– include directories
Always run git clean -dn first to see what would be deleted. Once you add -f, the removal is permanent.
Reset repository, discarding all changes
git reset --hard
git reset --hard discards all local changes in the working tree and index. Only use this when you are sure you don’t need any uncommitted work.
Checkout a file from another branch
Instead of cherry‑picking an entire commit, it is possible to check out a file from another branch into the current working folder.
git checkout branchname path/to/filename
Show the commit history for a specific file
git log -p -- path/to/file
Show objects using the most space
The following command shows all git blob objects sorted from the smallest to the largest. This command is useful to see which commits are using lots of space in the repository.
git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| sed -n 's/^blob //p' \
| sort --numeric-sort --key=2 \
| cut -c 1-12,41- \
| $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest
Git Configuration
Run git commands recursively
Adding the following alias to git config allows running git commands recursively on all git repositories within a subfolder.
git config --global alias.all '!f() { ls -R -d */.git | xargs -I{} bash -c "echo {} && git -C {}/../ $1"; }; f'
With the alias in place, it is now possible to run the following command to work on multiple repositories at the same time.
git all pull
git all "checkout master"
Visually pleasing git logs
Adding the following alias to git config allows viewing the git log in a more digestible format.
Read the full article from the author of this neat trick. 👉 Mattias Geniar: Pretty git log in one line
git config --global alias.logline "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
After the previous alias the git log can be viewed with better formatting and concise information.
git logline
Show git info in bash prompt
Show the currently checked out branch in the bash prompt while maintaining bash prompt colors. Download the .git-prompt.sh file from the git main repository and save it to a location in your local file system. In this case, in a subfolder called .mystuff which is located inside of my home folder.
https://github.com/git/git/tree/master/contrib/completion
# Show working directory git branch.
source ~/.mystuff/.git-prompt.sh
# PS1='\n\033[01;34m\]\w\[\033[95m\]$(__git_ps1 " (%s)")\n${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\\$
# PS1='\n👻 \t \[\033[01;34m\]\w\[\033[95m\]$(__git_ps1 " (%s)")\n\[\033[00m\]\[\033[32m\]${debian_chroot:+($debian_chroot)}\u@\h\[\033[00m\]:\\$ '
# Enable AWS autoprompt
PS1='\n👻 \t - \[\033[32m\]${debian_chroot:+($debian_chroot)}\u@\h\[\033[00m\]\[\033[95m\]$(__git_ps1 " (%s)")\n\[\033[01;34m\]\w\[\033[00m\] \$ '
Windows Config Settings
On Windows systems git will attempt to automatically convert between Windows and Linux style line endings. This causes issues when working with repositories located inside of the WSL from both inside Linux (bash) and PowerShell.
Since most modern code editors can be configured to use Linux style line endings it is easiest to disable the automatic conversion of line endings.
git config --global core.autocrlf false
This setting can also be encoded into the git repository. Simply check in a file called .gitattributes with the following settings into the repository root.
* text=auto eol=lf
*.{cmd,[cC][mm][dD]} text eol=crlf
*.{bat,[bB][aa][tT]} text eol=crlf
Additionally on the Windows side disable tracking the file mode. Without this option (default) git diff will flag the difference in file permissions, which are inherently different when navigating to the Linux subsystem through PowerShell.
On the Windows side disable this globally.
git config --global core.fileMode false
Conflict Style
Git can be configured to provide three‑way merge information for resolving merge conflicts. To do so issue the following command.
git config --global merge.conflictstyle diff3
After configuring this option git will also provide the common ancestor of the two file versions being compared.
Patching between branches
Suppose you are working on a feature branch that is shared with a co‑worker. Both of you are committing to this feature branch. Also, to ensure you
keep up to date with changes from the rest of the team one of you regularly merges changes from develop into your feature branch.
Several days or weeks pass and now you wish to cleanly merge your changes and re‑organise your commits. One way to do this is by
constructing a patch. The patch will essentially contain only those changes missing from the develop branch and not include all commits that were
merged. Note, this will essentially look like all your changes happened at once and all commits from yourself and your team will be gone. Instead
you can now re‑organise a new set of commits.
git diff $(git merge-base develop feature/foo) > /tmp/patch.diff
git checkout develop
git apply /tmp/patch.diff
Show diff inside a PR
git diff --name-only origin/develop...origin/pr
Note the usage of three dots which means: show only changes in the source branch, starting at a common ancestor of both branches. It will not show any changes made to the destination branch.
This is in contrast to the two dots which show changes in both the source and destination branches.