Skip to main content

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
tip

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
caution

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
caution

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

~/.bashrc
# 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.

.gitattributes
* 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.