Git Cheatsheet

Commands

Notes:

  • origin is the default remote, you can always specify another remote name
  • ^: "parent of", e.g. git show HEAD^ means "show me the parent commit of HEAD". If followed by a number, is the n-parent, so useful for merge commits only
  • ~: "first parent of", e.g. git show HEAD~3 means "show me the parent of the parent of the parent of HEAD"
  • {x}: History position, to be used from commands like reflog
  • ..: range specification: e.g. git log A..B shows changes in B not yet in A
  • ...: exclusion range specification: commits that are in either of the references but not in both
  • --not: exclude commits not reachable by a reference, e.g. git log A B --not C shows changes either at A or B, but not present in C

Branch Management

  • git checkout -b <new-branch-name> : get a new branch and switch to it
  • git checkout -b <branch-name> : get a local copy of a remote existing branch
  • git checkout <branch-name> : switch to an existing branch
  • git checkout --orphan <branch-name> : create branch without full history
  • git fetch: update your local repo reference list (list of branches and latest commits they point to)
  • git pull origin <branch-name>: update commits info from a branch
  • git pull --rebase: Pull changes, and if both your local and the remote had changes, rewrite local history by placing server commits before, and yours after them. Does not add a merge commit
  • git merge --no-ff <source-branch> : merge into current branch source one without rebase/FF. This will create a new merge commit
  • git push origin <destination-branch> : push merges/changesets to a branch
  • git push origin <local-branch>:<remote-branch> : push merges/changesets to a different branch than local
  • git push origin <destination-branch> --force-with-lease : push merges/changesets to a branch. If remote had different commits not in local, fails and does not push. Safer than --force which would always override remote commits
  • git remote -v: show all remotes configured in the repository
  • git remote show origin : display the path of the repository
  • git remote set-url origin xxx : Change remote URI to xxx
  • git remote rm <name> / git remote remove <name> : Remove a remote
  • git remote rename <old> <new>: Rename a remote (just the name, not the URI)
  • git remote add origin git@github.com:<path>.git: replace the origin remote URI. Need to firstgit remote rm origin to remove the previous one
  • git remote add <user> git@github.com:<user>/<path>: add <user> fork to a repository as a remote. When pushing changes afterwards to that remote, Github will propose you to create a pull request directly from the fork remote towards the original remote
  • git pull <user>: fetch branches from remote <user>
  • git add xxx : add files (use . for everything, <folder>/.. for folder recursive children)
  • git add -i: interactive staging; allows to decide what to do with each local change (often with the patch option)
  • git commit : commit changes
  • git status : show status of uncommited files
  • git checkout <filename> : revert a file
  • git checkout <branch-name> <filename> : Checkout all changes to <filename> from branch <branch-name> into current
  • git checkout <revision> . : revert a full branch to specified revision if not commited
  • git revert <commit1> <commit2> ...: Reverts certain commits if commited
  • git clean -n: dry run to check which uncommited modifications would be removed
  • git clean -f -d : remove all local uncommited modifications
  • git branch : display local branches, active one is with an *
  • git branch -vv: display additional information. Remember state is only regarding local git repo, not remote(s). Reflects state since last fetch
  • git branch --sort=-committerdate # DESC: display local branches, ordered by last commit date
  • git branch -r: list all remote branches
  • git diff : Show changes in files
  • git diff <branch-name> origin/<remote-branch-name> : show a diff between a local branch and a remote one from the origin remote
  • git --no-pager diff --name-only master...HEAD: list all modified files in commits from current branch in regards to master up to your last pull
  • git rebase <branch-name> : rebases current branch with specified branch (fetches remote branch changes and then adds your changes at the tip)
  • git rebase -i <branch-name>: rebases current branch with specified branch, allowing you to reorder changes
  • git rebase -i HEAD~3: allows you to check and reorder, mix or remove the last 3 commits from the current branch. Very useful to rewrite local commits, squash some of them, etcetera, before preparing a branch for review
  • git rebase --onto <A-branch> <B-branch> <C-branch>: Rebase commits from C not present at B, into A; assuming that B was branched from A, and C was branched from B ("skip the intermediary").
  • git rm <filename> : delete a file from branch and filesystem
  • git branch -d <branch-name> : delete a local branch
  • git push origin --delete <branch-name> : delete a remote brach
  • gitk <filename> : show visual git log
  • git reset <revision-hash> .: revert a full branch to specified revision if commited
  • git reset --soft HEAD~1: reset to last commit (even if pushed). Changes will be staged, and can be committed again, but if pushed before, you need to push with --force-with-lease
  • git reset --hard HEAD^: forcibly resets to the branch's head, discarding any commit
  • git reset --hard origin/<branch-name>: forcibly resets your local branch to the remote version. Helpful when gets easy to just discard any local operations and revert to the old state
  • git reset HEAD <file>: reset <file> to the version in HEAD
  • git reset --soft <new-root-hash> && git commit --amend -m "<new message>" && git push --force: squash all branch pushed commits previous to the one specified into a single commit with the desired new message
  • git reset 'HEAD@{1}': revert to the previous command's commit. Check the reflog to see which command was last. This is very useful to undo non-trivial commands like a git reset HEAD~1
  • git reset HEAD@<commit>: revert to a specific commit (often from the reflog)
  • git submodule update --init --recursive : Init and update all submodules
  • git submodule foreach --recursive git reset --hard: Reset all submodule changes
  • Switch from current branch having a submodule to a branch without it:
rm -Rf <submodule-folder>
git reset && git checkout 
git checkout <branch-name>
  • git pull https://github.com/<username>/<repository-name>.git <branch-name>: Merge a pull request to local branch
  • git checkout --theirs xxxx git checkout --ours xxxx: Keep changes from incoming branch or local one, respectively
  • git cherry-pick <commit>: merges and commits a specific commit to current branch. Note that SHA of the commit will change (as the date changes)
  • git commit --amend: Squash a change on previous commit and change the commit message
  • git commit --amend --author='Kartones <your@email.com>' --no-edit: Change the author of the last commit (note that the email is enclosed inside <>)
  • git rebase -i HEAD~3 -x "git commit --amend --author='Kartones <your@email.com>' --no-edit": Change the author of the last 3 commits
  • git diff --staged: Normal git diff shows only unstaged changes, with --staged you can see staged changes that will be committed
  • Undo a commit removing it from history:
git reset --hard HEAD~1
# your new commit goes here
# option a:
git push origin <branch> --force-with-lease
# option b: (more dangerous, see below)
git push origin <branch> --force
  • When pushing, --force will destroy any commit added by others to the remote. --force-with-lease tries to keep all upstream commits, and if it can't (because there is a conflict), it will abort and notify you.
  • Tag any commit of a repo (e.g. with a certain version):
git tag <label> <commit-id>
git push origin <label>
  • Apply a .diff file: git apply <filename>.diff
  • Push to a different remote branch: git push origin <localb-ranch>:<remote-branch>
  • Rename a branch: git branch -m <old-name> <new-name>
  • git commit --no-verify ...: With great power comes great responsibility. This flag disables all commit hooks, so use it only when really in need
  • git fetch origin master && git rebase origin/master && git push origin HEAD --force-with-lease: Rebase master with any new remote change, and then push, but not forcing if there is any kind conflict with the push. Also works if there's any amended commit

Stashing

  • git stash: Stash current changes
  • git stash -u: Stash also the untracked changes
  • git stash apply: Unstash and merge stored changes
  • git stash list: check all stashes

Logs, Search

  • git log -n X -p : show X last commits with diffs
  • git log <branch-A-name> ^<branch-B-name> : commits in branch A that aren't in branch B
  • git log -- <path>: filter to commits including modifications to <path>/file
  • git log --pretty=oneline --stat --all <folder-name> : same as previous, but better presented
  • git log --format='%H' -1 HEAD: Get last commit hash from current branch
  • git log --pretty=format:"%h %s" --graph: format the commits log as nice graph with hash & commit message
  • git rev-list origin/master...master: list all commits that exist on local master but not on origin/master
  • git reflog: show a history of changes in all branches
  • git show HEAD@{3}: show commit details (easiest way to combine with reflog)
  • git log origin/<branch-name>..<branch-name> : Show diff between remote commits and local commits
  • git log <branch-name>..origin/<branch-name> : Show diff between local commits and remote commits
  • git blame -M: Blames original commit, not the move commit
  • git blame -CCC: Looks at all commits in history
  • git log -S <string>: find all commits that modified occurrences of <string>, e.g. git log -S myFunction (+ info)
  • git log -G <regex>: Search in which commits the regular expression matches
  • git tag -l "v1.*": Searching for tags supports wildcard via the -l option
  • git grep: Search patterns in tracked files (+ info)
  • git merge-base <branch-A> <branch-B>: Find common ancestor commit between two branches

Configuration

  • git config --list : List currently setup config values
  • git config --global user.name "<username>" : Setup global user name to <username>
  • git config --global user.email "<email>" : Setup global user email to <email>
  • git config --global credential.helper 'cache --timeout=28800' : Make git cache credentials for 8 hours
  • git config --global color.ui true : Activate colors in diffs, etc
  • git config --global core.autocrlf input : Fix Convert newlines to Unix-style ones (Unix)*
  • git config --global core.autocrlf true : Fix Convert newlines to Unix-style ones (Windows)
  • git config --global core.excludesfile ~/.gitignore : Instruct git to always ignore patterns defined at ~/.gitignore
  • git config --global pager.log 'diff-highlight | less': Better diff highlighting (same for 3 following options)
  • git config --global pager.show 'diff-highlight | less'
  • git config --global pager.diff 'diff-highlight | less'
  • git config --global interactive.diffFilter diff-highlight
  • git config --global core.editor <editor-name>: change default editor (for commit messages, etcetera)

Tools

  • git -C <path> <command> ...: Run git commands as if current folder was <path>
  • When you push changes, the format of the push output's last line is: <oldref>..<newref> <from-branch> -> <to-branch>
  • cli: GitHub’s official command line tool. Augment with the following (third party):
    • git extras: Many tools, but I use it just because I can see branches ordered by last activity via git brv
    • poi: Tool to delete merged branches (checks PRs) via gh poi

Third-party Tools

  • tig: to navigate commits & branches
  • Github:
  • hub: CLI tool to better interact with Github from the command-line. I now recommend to use instead cli (the official GH tool)
  • Commands for automatically closing tickets when merged to default branch
  • Search to display all issues/PRs of an organization: https://github.com/issues?utf8=%E2%9C%93&q=is%3Aopen+org%3Athemotion+sort%3Aupdated-desc
  • Additionally, filter to things assigned to me or involving me: https://github.com/issues?utf8=%E2%9C%93&q=is%3Aopen+org%3Athemotion+sort%3Aupdated-desc+involves%3Akartones

GitHub - Searches

GitHub - Security

Tutorials

xkcd: Git https://xkcd.com/1597/Git conceptual model - https://blog.acolyer.org/2016/10/24/whats-wrong-with-git-a-conceptual-design-analysis/

  • official documentation + free book (really good!)
  • Spark Code Hub Git Tutorial: Compact and direct to the point, covers all the relevant parts
  • Mental model: Git keeps three trees (note this is local, not factoring in remotes):
    • HEAD: Branch status, last commit reference
    • Stage: staged files that will be sent to HEAD
    • Working directory: local file-system files (unstaged and/or untracked content)
  • Commit messages should be in imperative form, e.g. "Fix bug"
  • 9 useful tricks of git branch
  • Most Common Git tips & tricks (awesome list)
  • Syncing a fork (first configure remote upstream)
  • supersedes: when a branch replaces a previous branch that has been closed without merging.
  • My preferred approach to working with forks:
    1. Clone the main upstream, not your fork: git clone git@github.com:<user-or-org>/<repo>.git
    2. Sync and update submodules: git submodule sync --recursive; git submodule update --init --recursive
    3. Setup your fork as another upstream: git remote add $USER git@github.com:<your-github-user>/<repo>.git
    4. Disable pushes to main upstream: git remote set-url --push origin no_push
    5. Now push always to your upstream: git push $USER HEAD
  • Commitizen and Conventional Commits commit messages syntax (good practice in general):
    • feat: New feature (~ X.y.z)
    • fix: Bug fix (~ x.Y.z)
    • chore: Changes to auxiliary tools and libraries, tiny changes (~ x.y.Z)
    • build: Changes to the build/CI process
    • docs: Documentation only changes
    • style: Linting, formatting, etc. only changes
    • refactor: Change that neither fixes bugs or adds new features
    • perf: Change that improves performance
    • test: Change that adds or modifies tests

Optimizations

  • git config --global checkout.workers 0: Disable git's serial mode by enabling it to use one thread per CPU core. Should speed up operations in big or long-living repositories.
  • git maintenance start: Enable prefetch and other git operations to happen in background (~hourly) for a repository.
  • git-lfs + install guide: Support large files. Linux TL;DR: Follow instructions at git-lfs.com + sudo apt install git-lfs + git lfs install from the target repo
  • sparse checkouts: Fetch only a subset of files/folders. More info
  • shallow clone: Truncate git history to a specified number of commits.
  • partial clone: Get only a subset of files given a filter. More info about partial and shallow clones.
  • git scalar: Tool for large repositories
Git Cheatsheet page, written by Kartones