Branches

  • git checkout -b <branchname> - create a new branch
  • git checkout <branch> - switch to an existing branch
    • I think git switch <branch> also works now, but I’m old
  • Rename a branch:
    • git branch -m <oldname> <newname> - rename a branch locally
    • git push <remote> :<oldname> <newname> - rename a branch on the remote
  • Delete a branch:
    • git branch -d <name> - delete a branch locally
    • git push -d <remote> <branch> - delete a branch on the remote

Undoing things

  • git restore <filename> - restore those files to their state at last commit (wipe staged/unstaged changes)
  • git reset - manipulate the local head
    • git reset --soft <ref> - Move to the specified ref, but don’t actually touch anything on disk. Changes made since <ref> will end up in staging.
      • git reset --soft HEAD~1 - Effectively an undo button for git commit. Useful if you fatfinger a commit message.
    • git reset --hard <ref> - Move to the specified ref, discarding changes
  • git revert <ref> - Create a new commit which precisely undoes the changes made in <ref>

History analysis

  • git blame <file> - show a line-by-line view of which commit last changed each line of the specified file (comit, author, date/time)
    • If you don’t see something you expect, check for a .git-blame-ignore-revs file in the repository root. Refs listed there will not be shown in the blame.
  • git log - show history graph leading up to current head
  • git log -n <n> - show only the previous <n> commits (including HEAD)
  • git log -p - include the actual code differences
  • git log --name-only — show the paths/filenames of files which were changed in each commit, but not the full code diffs
  • git log --graph - draw ASCII-art graph of branches
  • git log <file> - only show commits pertinent to the specified file
    • git log -- <file> for deleted files
    • git log --follow <file> to try extra hard to follow renames
  • git log -a - show commits on all branches, even those not merged into current branch
  • git log --oneline - abbreviate the full message in to one-line-per-commit
  • git log <ref> - show a log up to the specified reference
    • <ref> may be a commit SHA, branch name, or other ref-like
  • git log <ref1>..<ref2> - show longs from <ref1> (not inclusive) up to <ref2> (inclusive)
    • You can use HEAD as one of those ID’s to pull the head of the branch you’re currently on, like git log 1234567..HEAD to view commits made after 1234567
  • git log --before <date1> --after <date2> to filter commits by date
    • Format dates like YYYY-MM-DD. Example: git log --before 2023-05-01
    • You can use either --before or --after on their own, or in combination
  • git log -S <string> - use the pickaxe to search history for changes which include (adding or removing) <string>
    • Example: git log -p -S tomato finds commits which added or removed the word tomato
    • If you want to find strings with weird characters (spaces ARE weird), you’ll need to wrap it in quotes

Useful combinations:

  • git log --graph --oneline - highly compressed history, but visually showing the changes made to this point
  • git log --follow -a -- <file> — show the history of a deleted <file>
  • git log -p | grep -B 1 "+++ /dev/null" | grep "---" | cut -c 7- - list all files that have been deleted from this repo up to this point (warning: may be slow if many large files have been deleted / moved, like repos full of large MS Word documents)

Personal favorite - append the following to ~/.bashrc, then use gitflowlog:

alias gitflowlog="git log --pretty=format:'%C(auto,yellow)%h %C(auto,green)%an %C(auto,blue)%ad %C(auto,magenta)%G? %C(auto,reset)%s' --color --graph --date=short"

A better way

I should use a proper git alias instead of that bash alias. But i don’t. Sue me.

The reflog

The reflog is unlike the regular git log — it does not show a commit graph. Instead, it shows a history of all recent local operations.

  • git reflog - show what the user has recently done, including commits made, branch switching, push/pull, and a few others.
    • This is a default alias for git reflog show.
  • git reflog -n <n> - show only <n> previous reflog entries
  • git reflog list - list ref names which have a historical reflog available for viewing.

You can use the reflog and its special historical reference names (the HEAD@{n} names) sometimes as a “get out of jail free” card if you really screw up — unlike the HEAD~n refs which reach backwards along the commit history graph, HEAD@{n} reaches backwards in operations. So, if you completely botch a rebase or something, you can often git reset --hard HEAD@{n} back to before you started.

git