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 ofHEAD
". 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 ofHEAD
"{x}
: History position, to be used from commands likereflog
..
: range specification: e.g.git log A..B
shows changes inB
not yet inA
...
: 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 atA
orB
, but not present inC
Branch Management
git checkout -b <new-branch-name>
: get a new branch and switch to itgit checkout -b <branch-name>
: get a local copy of a remote existing branchgit checkout <branch-name>
: switch to an existing branchgit checkout --orphan <branch-name>
: create branch without full historygit 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 branchgit 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 commitgit merge --no-ff <source-branch>
: merge into current branch source one without rebase/FF. This will create a new merge commitgit push origin <destination-branch>
: push merges/changesets to a branchgit push origin <local-branch>:<remote-branch>
: push merges/changesets to a different branch than localgit 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 commitsgit remote -v
: show all remotes configured in the repositorygit remote show origin
: display the path of the repositorygit remote set-url origin xxx
: Change remote URI to xxxgit remote rm <name>
/git remote remove <name>
: Remove a remotegit 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 onegit 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 remotegit 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 thepatch
option)git commit
: commit changesgit status
: show status of uncommited filesgit checkout <filename>
: revert a filegit checkout <branch-name> <filename>
: Checkout all changes to<filename>
from branch<branch-name>
into currentgit checkout <revision> .
: revert a full branch to specified revision if not commitedgit revert <commit1> <commit2> ...
: Reverts certain commits if commitedgit clean -n
: dry run to check which uncommited modifications would be removedgit clean -f -d
: remove all local uncommited modificationsgit 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 fetchgit branch --sort=-committerdate # DESC
: display local branches, ordered by last commit dategit branch -r
: list all remote branchesgit diff
: Show changes in filesgit diff <branch-name> origin/<remote-branch-name>
: show a diff between a local branch and a remote one from theorigin
remotegit --no-pager diff --name-only master...HEAD
: list all modified files in commits from current branch in regards tomaster
up to your last pullgit 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 changesgit 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 reviewgit rebase --onto <A-branch> <B-branch> <C-branch>
: Rebase commits fromC
not present atB
, intoA
; assuming thatB
was branched fromA
, andC
was branched fromB
("skip the intermediary").git rm <filename>
: delete a file from branch and filesystemgit branch -d <branch-name>
: delete a local branchgit push origin --delete <branch-name>
: delete a remote brachgitk <filename>
: show visual git loggit reset <revision-hash> .
: revert a full branch to specified revision if commitedgit 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 commitgit 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 stategit reset HEAD <file>
: reset<file>
to the version inHEAD
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 messagegit reset 'HEAD@{1}'
: revert to the previous command's commit. Check thereflog
to see which command was last. This is very useful to undo non-trivial commands like agit reset HEAD~1
git reset HEAD@<commit>
: revert to a specific commit (often from thereflog
)git submodule update --init --recursive
: Init and update all submodulesgit 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 branchgit checkout --theirs xxxx
git checkout --ours xxxx
: Keep changes from incoming branch or local one, respectivelygit 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 messagegit 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 commitsgit diff --staged
: Normalgit 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 needgit fetch origin master && git rebase origin/master && git push origin HEAD --force-with-lease
: Rebasemaster
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 changesgit stash -u
: Stash also the untracked changesgit stash apply
: Unstash and merge stored changesgit stash list
: check all stashes
Logs, Search
git log -n X -p
: show X last commits with diffsgit log <branch-A-name> ^<branch-B-name>
: commits in branch A that aren't in branch Bgit log -- <path>
: filter to commits including modifications to<path>
/filegit log --pretty=oneline --stat --all <folder-name>
: same as previous, but better presentedgit log --format='%H' -1 HEAD
: Get last commit hash from current branchgit log --pretty=format:"%h %s" --graph
: format the commits log as nice graph with hash & commit messagegit rev-list origin/master...master
: list all commits that exist on localmaster
but not onorigin/master
git reflog
: show a history of changes in all branchesgit show HEAD@{3}
: show commit details (easiest way to combine withreflog
)git log origin/<branch-name>..<branch-name>
: Show diff between remote commits and local commitsgit log <branch-name>..origin/<branch-name>
: Show diff between local commits and remote commitsgit blame -M
: Blames original commit, not the move commitgit blame -CCC
: Looks at all commits in historygit 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 matchesgit tag -l "v1.*"
: Searching for tags supports wildcard via the-l
optiongit 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 valuesgit 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 hoursgit config --global color.ui true
: Activate colors in diffs, etcgit 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
- git extras: Many tools, but I use it just because I can see branches ordered by last activity via
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
- Issues in which you're mentioned
- Pull requests in which you're mentioned
- All open issues and pull requests of organization
TEST
: Change to proper organization name, and for example can filter to all assigned to you - When comparing tags/branches, in the URL
X..Y
is to show code differences, whileX...Y
shows the differences in commits (which commits are missing).
GitHub - Security
- Anyone can Access Deleted and Private Repository Data on GitHub: Interesting reading. Not trivial, but neither too hard to brute-force, so careful with your deleted forks, deleted repositories and even with private repositories.
Tutorials
- 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:
- Clone the main upstream, not your fork:
git clone git@github.com:<user-or-org>/<repo>.git
- Sync and update submodules:
git submodule sync --recursive; git submodule update --init --recursive
- Setup your fork as another upstream:
git remote add $USER git@github.com:<your-github-user>/<repo>.git
- Disable pushes to main upstream:
git remote set-url --push origin no_push
- Now push always to your upstream:
git push $USER HEAD
- Clone the main upstream, not your fork:
- 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 processdocs
: Documentation only changesstyle
: Linting, formatting, etc. only changesrefactor
: Change that neither fixes bugs or adds new featuresperf
: Change that improves performancetest
: 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
: Enableprefetch
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