Git tips

rtags: programming, git

How to get the changes on a branch in Git

# Changes on branch but not on HEAD (three dots)
git diff HEAD...branch

List recent branches and switch

$ git checkout $(git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs | pick | cut -f2)
# .gitconfig alias
branches = "!sh -c \"git checkout $(git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs | pick | cut -f2)\""

Source. Uses pick.

See branches merged into other branch

git branch --merged master    # lists branches merged into master
git branch --merged           # lists branches merged into HEAD (i.e. tip of current branch)
git branch --no-merged        # lists branches that have not been merged
# add -a for all branches (local/remote) or -r for remote only


Finding best common ancestors of two commits/branches

git merge-base <commit> <commit>


Check if the branch is current

$ git fetch && git branch -r --merged | grep -q origin/master && echo Incorporates origin/master || echo Out of date from origin/master

# In ~/.gitconfig
   current = !git branch -r --merged | grep -q $1 && echo Incorporates $1 || echo Out of date from $1 && :

And then run:
$ git current origin/master


Check if branch can merge without conflicts

git merge other-branch --no-commit --no-ff
git merge --abort


See commits from a branch but not from merged in branches

git log --first-parent


See what is on a branch

# Find commit on this
# branch that changed something in the current folder
git log $(git merge-base first_branch HEAD)..HEAD .

git log --no-merges master..
git log --no-merges master..HEAD --author="Jason" .

See files in conflict

git diff --name-only --diff-filter=U

Check for conflict markers in code

git diff --check

Leaderboards - number of commit by user sorted

git shortlog -sn --all --no-merges
git shortlog -sn --since='10 weeks' --until='2 weeks'

See recent branches you have been working on

git for-each-ref --count=10 --sort=-committerdate refs/heads/ --format="%(refname:short)"
# alias
recent = "for-each-ref --count=10 --sort=-committerdate refs/heads/ --format='%(refname:short)'"

Remind yourself what you have been doing

git log --all --oneline --no-merges --author=igor.dejanovic
# alias
recap = "log --all --oneline --no-merges --author=igor.dejanovic"

See what is changed in the merge conflict resolution

git diff hash hash^1 hash^2


git rerere - reuse recorded resolutions

Delete local branches whose remotes were deleted

git config --global alias.gone "! git fetch -p && git for-each-ref --format '%(refname:short) %(upstream:track)' | awk '\$2 == \"[gone]\" {print \$1}' | xargs -r git branch -D"

Source. Now git gone will delete all local branches whose remotes were deleted.

Find large files in the repo history

  • This works but is slow for large repos.
git rev-list --all | while read rev ; do git ls-tree -rl --full-name $rev ; done | sort -k4 -nr | uniq > large.txt
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- |
  numfmt --field=2 --to=iec-i --suffix=b --padding=7 --round=neares

Compare two branches

Some commands use kompare or meld.

  • Show only file names ignoring whitespace (-w):
        git diff -w --name-status master..integration
  • Show changes between tips of two branches.
        git diff master..integration | kompare -
  • See the diff of modified files only between two branches in folder src.
        git diff -w --diff-filter=M master..integration src/ | kompare -
  • See what is on branch integration but not on master (notice three dots).
        git diff master...integration | kompare -
  • To use meld in previous recipes do the following:
    1. Configure meld as a diff tool:
                git config --global diff.tool meld
    2. Use git --dir-diff. For example:
                git difftool -d master...integration