Git CheatSheet
Learn GIT: https://learngitbranching.js.org/
Contents:
Cherry-pick
NOTE: cherry-pick from current to another branch is impossible, you always need to checkout!
# pick the commit from "feature" branch to "main" branch git checkout main git cherry-pick abc123 # pick multiple non-consecutive commits git cherry-pick abc123 def456 ghi789 # pick a range of commits git cherry-pick abc123..def456 # resolve conflicts (if occur) git cherry-pick --continue # Abort the cherry-pick git cherry-pick --abort
Stash
By default git SKIP untracked or ignored files for stash.
# Stash modified/staged files git stash # Stash modified/staged/untracked files git stash -u # Stash modified/staged/untracked/ignored files git stash -a # Stash modified/staged files with message git stash save "stash message" # Show all available stashes git stash list # Get stash to working gir & delete the stash (last or specified) git stash pop git stash pop stash@{1} # Get stash to working gir, but not delete the stash (last or specified) git stash apply git stash apply stash@{1} # Recover dropped stash (you need to know it's hash) git stash apply [stash-hash] # Delete stash (last or specified) git stash drop git stash drop stash@{1} # Show stash diff (last or specified) git stash show git stash show stash@{1} # Show all details (the patch) git stash show -p stash@{1} # Create branch from stash & delete stash (last or specified) git stash branch [branch-name] git stash branch [branch-name] stash@{1}
Remote, Fetch, Pull, Push
fetch
Retrieving updates from another repository and updating local repos
# Add a git URL as an alias git remote add [alias] [URL] git remote add origin [email protected]:owner/repo.git # Fetch down all branches from remote repo git fetch # or with alias git fetch origin # Fetch and delete remote branches locally (if it does not exist on remote) git fetch --prune
pull
# (fetch + merge) Fetch and merge commits from related remote branch git pull # Pull and remove deleted remote branches git pull --prune # Updates your branch only if it can fast-forward (without creating new merge commits) git pull --ff-only # (fetch + rebase) Fetch commits and reapplies your commits on top git pull --rebase # Fetches branch from "origin" and updates your local branch # Updates local branch manually without merge/rebase. # Can be done on other branch (NOT current checkouted). git fetch origin branch:branch # pull --force - there is no "pull --force" # To force your local branch to match the remote branch: git fetch origin && git reset --hard origin/branch_name
push
# push current branch to linked upstream git push # push current branch and set tracking branch # Eg: if current branch is xyz - pushes xyz to origin/xyz git push --set-upstream origin HEAD git push -u origin HEAD # the same but set origin branch name # Eg: if current branch is xyz - pushes xyz to origin/branch_name # (creates origin/branch_name if not exists) git push --set-upstream origin branch_name git push -u origin branch_name # Push local branch commits to remote branch git push origin [branch] # Force push (with changing history) git push origin [branch] --forse = git push [alias] +[branch]
Merge, Rebase
merge
# merge the specified branch’s history into the current one git merge branch_name # merge the specified branch’s history into the current one # fail if linear history fails git merge branch_name --ff-only # merge a remote branch into your current branch to bring it up to date git merge alias_name/branch_name # git merge origin/my-feat # merge source_branch into target_branch git switch target_branch && git merge source_branch
rebase
# Rebase the current branch onto the specified branch, # which means the commits from the current branch will be # reapplied on top of the specified branch git rebase [branch] # Interactive Rebase all commits that go before specified one (using hash) git rebase -i 972078a # Interactive Rebase last 3 commits (using offset) git rebase -i HEAD~3 # Interactive Rebase starting from zero commit (root) git rebase -i --root
Doc: https://git-scm.com/docs/git-rebase
Checkout, Branch
checkout
# Switch to another branch and check it out into your working directory git checkout branch_name # Create branch on your local machine and checkout to it: git checkout -b new_branch_name # Create new branch from source branch (specify source exactly) git checkout -b new_branch_name source_branch_name
switch
# Create a local branch from the fetched remote branch (Git 2.23+) git switch [branch-name] # In this case Git is guessing that you are trying to checkout # and track the remote branch with the same name. # This can be disabled with --no-guess git switch [branch-name] --no-guess # -c to create a new local branch git switch -c [local-branch-name] origin/[remote-branch-name]
branch
# Show all local branches git branch # Show all local branches & last commit message git branch -v # Show branches & related remote branch (upstream) & last commit git branch -vv # Show all remote branches git branch -r git branch --remotes # Show local & remote branches git branch --all # List branches available for checkout git branch -v -a # Show of branches that already was merged with current git branch --merged # Show of branches that not merged with current git branch --no-merged # Create a new branch at the current commit git branch branch_name # Rename branch git branch --move old_branch_name new_branch_name # Relate remote and current branches git branch --set-upstream-to=origin/branch_name git branch -u origin/branch_name
Delete branch:
# Delete local branch only if it was fully merged git branch -d branch_name # Force delete local branch git branch -D branch_name # Delete remote branch git push origin --delete branch_name # OR git push origin :branch_name
Commiting
status
# show modified files in working directory, staged for your next commit git status
add
# Stage all repo files (not from .gitignore) git add . # Stage all changes in <directory> for the next commit. git add [directory] # Stage all changes in <file> for the next commit. git add [file]
commit
# commit your staged content as a new commit snapshot git commit -m "your commit message" # add & commit git commit -am "your commit message" # Append current changes to last commit git commit --amend # Append current changes to last commit (adds changes files too) git commit -a --amend # Append current changes to last commit (take massage from last commit) git commit -a --amend --no-edit # Create empty commit git commit --allow-empty -m 'Initial commit'
History
show
# show changes of the last commit git show # show any object in Git in human-readable format git show [SHA]
diff
# diff of what is changed but not staged git diff # diff of what is staged but not yet commited git diff --staged # show the diff of what is in branchA that is not in branchB git diff branchB...branchA
log
# show commits in the current branch’s history git log # Show all tree (even if HEAD is detached to another commit) git log --all # Show compact only last 5 commits git log --oneline -n5 # Show tree git log --graph git log --graph --oneline # display the commit history of a specific file, # tracing its changes even if it has been renamed or moved git log --follow [file] # see the git log of a specific branch git log <branch-name> # show the commits on branchA that are not on branchB git log branchB..branchA
Search (in log)
# Search for added/removed lines with a specific string git log -S "search_term" # Search by pattern in diffs git log -G "regex_pattern" # Include File and Diff Details git log -p -G "search_term" # Search Across All Branches git log --all -S "search_term"
Tagging
# list all tags git tag git tag -l git tag --list # see tag data along with the commit that was tagged git show v1.4 # search for tags that match a particular pattern git tag -l "v1.8.5*" # create a simple tag (holds only commit) git tag v1.4 # create an annotated tag (holds commit and tag data) git tag -a v1.4 -m "Version 1.4" # create a tag later for commit 9fceb02 git tag -a v1.2 9fceb02 # push tag git push origin v1.5 # push all tags git push origin --tags git push --tags # delete tag (local only) git tag -d v1.4 # delete tag remotely git push origin --delete v1.4 # checkout the tag commit git checkout v1.4
clone, init (create repo)
# Create Git repo in current folder git init git init <project name> # Create remote repo in current folder by URL git clone <URL> # Copy remote repo in specified folder by URL git clone <URL> <folder> # Copy remote repo with only specified branches git clone -b <branch_name> --single-branch <URL> # Copy remote repo with only specified branches in specified folder git clone -b <branch_name> --single-branch <URL> <folder> # Copy remote repo with 5 commits last only (limit history) git clone <URL> --depth=5 <folder>
config
Remote
# view remote URLs git remote -v # add remote repo (takes two arguments) git remote add origin [email protected]:USERNAME/REPOSITORY.git # change a remote repository's URL (takes two arguments) git remote set-url origin [email protected]:USERNAME/REPOSITORY.git # rename a remote repository (takes two arguments) git remote rename origin my_name
More: https://docs.github.com/en/get-started/getting-started-with-git/managing-remote-repositories
List
# Show all settings git config --list # Or see files: `~/.gitconfig` (user wide) `.git/config` (repo wide) # Show global options only git config --global --list # Show system options only git config --system --list # Show options and files where they defined (global, user, repo, etc...) git config --list --show-origin
Get
# Show option value git config user.name # or git config --get user.name # Show option value and file where it places git config --show-origin user.name # Show option value from specified scope git config --system user.name
Set
# Set exact setting for repo scope git config branch.master.merge refs/heads/master # Set exact setting for global scope git config --global user.name "[Kama]" git config --global user.email "[[email protected]]" # Set automatic command line coloring for Git for easy reviewing git config --global color.ui auto # Set `core.autocrlf=true` in global scope git config --global core.autocrlf true # Set system wide .gitignore patern for all repos git config --global core.excludesfile [file]
Remove / Unset
# Remove option from repo scope git config --unset user.name # Remove option from global scope git config --global --unset user.name
Aliases
See: https://github.com/mathiasbynens/dotfiles/blob/main/.gitconfig
# add alias "git lg" git config --global alias.lg "log --oneline --graph"
[alias] # List aliases. aliases = config --get-regexp alias # List contributors with number of commits. contributors = shortlog --summary --numbered # Show the user email for the current repository. whoami = config user.email # Amend the currently staged files to the latest commit. amend = commit --amend --reuse-message=HEAD # View abbreviated SHA, description, and history graph of the latest 20 commits. l = log --oneline --graph -n20 # View the current working tree status using the short format. s = status -s # Show the diff between the latest commit and the current state. d = !"git diff-index --quiet HEAD -- || clear; git --no-pager diff --patch-with-stat" # Show verbose output about tags, branches or remotes tags = tag -l branches = branch --all remotes = remote --verbose # Interactive rebase with the given number of latest commits. reb = "!r() { git rebase -i HEAD~$1; }; r" # Remove the old tag with this name and tag the latest commit with it. retag = "!r() { git tag -d $1 && git push origin :refs/tags/$1 && git tag $1; }; r" # Remove branches that have already been merged with main. # a.k.a. ‘delete merged’ dm = "!git branch --merged | grep -v '\\*' | xargs -n 1 git branch -d" # Find commits by source code fc = "!f() { git log --pretty=format:'%C(yellow)%h %Cblue%ad %Creset%s%Cgreen [%cn] %Cred%d' --decorate --date=short -S\"$1\"; }; f" # Find commits by commit message fm = "!f() { git log --pretty=format:'%C(yellow)%h %Cblue%ad %Creset%s%Cgreen [%cn] %Cred%d' --decorate --date=short --grep=\"$1\"; }; f"
And more:
[alias] # Switch to a branch, creating it if necessary. go = "!f() { git checkout -b \"$1\" 2> /dev/null || git checkout \"$1\"; }; f" # `git di $number` shows the diff between the state `$number` revisions ago and the current state. di = !"d() { git diff --patch-with-stat HEAD~$1; }; git diff-index --quiet HEAD -- || clear; d" # Pull in remote changes for the current repository and all its submodules. p = pull --recurse-submodules # Clone a repository including all submodules. c = clone --recursive # Commit all changes. ca = !git add ':(exclude,attr:builtin_objectmode=160000)' && git commit -av # Credit an author on the latest commit. credit = "!f() { git commit --amend --author \"$1 <$2>\" -C HEAD; }; f" # Interactive rebase with the given number of latest commits. reb = "!r() { git rebase -i HEAD~$1; }; r" # Find branches containing commit fb = "!f() { git branch -a --contains $1; }; f" # Find tags containing commit ft = "!f() { git describe --always --contains $1; }; f" # Remove branches that have already been merged with main. # a.k.a. ‘delete merged’ dm = "!git branch --merged | grep -v '\\*' | xargs -n 1 git branch -d"
GIT Config Best Setup
https://blog.gitbutler.com/how-git-core-devs-configure-git/
[column] ui = auto [branch] # Show most recently changed branches first. sort = -committerdate [tag] sort = version:refname [init] defaultBranch = main [diff] algorithm = histogram colorMoved = plain mnemonicPrefix = true renames = true [push] default = simple autoSetupRemote = true followTags = true [fetch] prune = true pruneTags = true all = true # why the hell not? [help] autocorrect = prompt [commit] verbose = true [rerere] enabled = true autoupdate = true [core] excludesfile = ~/.gitignore [rebase] autoSquash = true autoStash = true updateRefs = true # a matter of taste (uncomment if you dare) [core] # fsmonitor = true # untrackedCache = true [merge] # (just 'diff3' if git version < 2.3) # conflictstyle = zdiff3 [pull] # rebase = true
Tracking (rm mv)
# delete the file from project and stage the removal for commit git rm [file] # Remove single file from git stage git rm --cached www/.env # change an existing file path and stage the move git mv [existing-path] [new-path]
Revert
# Creates new commit in which all changes of another commit will be reverted git revert 0ad5a7a6 # Revert by modifying your working tree and index without creating a commit git revert -n 0ad5a7a6 git revert --no-commit 0ad5a7a6 # The target commit is 2 commits behind HEAD on the current branch git revert HEAD~2 # Revert a set of Git commits, between two revisions. # The older commit should come first, followed by the newer commit. # Revert these two commits, plus every commit in between them. git revert HEAD~5..HEAD~2 # Revert merge and leave only 1 parent git revert -m 1 HEAD git revert --mainline 1 HEAD
Reset
reset
git reset = git reset --mixed HEAD git reset HEAD git reset [hash] # reset last two commits git reset HEAD~2 # reset all: commit history, stage snapshot, working dir git reset --hard [hash] # reset: commit history, stage snapshot git reset --mixed [hash] # reset: commit history git reset --soft [hash] # unstage a file, but retaining the changes in working dir git reset [file] # pull --force - there is no "pull --force" # To force your local branch to match the remote branch: git fetch origin git reset --hard origin/<branch_name>
reflog
# log of all ref updates (e.g., checkout, reset, commit, merge) git reflog # undo the specified operation git reset HEAD@{1} git reset d27924e
Grep (serach)
# Search "search_query" in working dir git grep -n search_query # Find commits where ZLIB_BUF_MAX exists git log -S ZLIB_BUF_MAX --oneline # Search with Regex git log -G regex --oneline
Submodules
https://git-scm.com/docs/git-submodule
# initializes all the submodules. In other words - sets up all # submodules of the project to be fetched and updated. git submodule update --init # OR git submodule init && git submodule update # Provides info about submodules. Shows the current commit # that each submodule is on, including an optional short status if any # of the commits have not been checked out. git submodule status # Status symbols: # "-" (minus sign): Submodule not checked out yet. # " " (space): Checked out but commit doesn’t match any tracked branch. # "+" (plus sign): Local changes or new commits in submodule. # "U": Merge conflicts in submodule. # Checkout all submodules to the expected commit - commit that currently # specified for submodule (it may be in .gitmodules file). For example # if your .gitmodules file has been changed to specify a different commit # then calling "update" makes the submodule checkout that commit. git submodule update git submodule update path/to/submodule # Go into your submodules and fetch and update them to the latest commit # on their main branch (pull the latest changes from the remote repository). # checkout submodules to the latest commit on the branch specified in # .gitmodules file. For example if new commits have been made to the submodule # remote repo you can call "update --remote" to get those new changes. git submodule update --remote git submodule update --remote -- path/to/submodule # Unregister specified submodule in git. And Clears submodule folder (files) # leaves only one file with hash (dir). git submodule deinit path/to/submodule # Unregister all submodules git submodule deinit --all # Remove a submodule from .gitmodules file: git config --file .gitmodules --remove-section submodule.path/to/submodule
-
See: https://education.github.com/git-cheat-sheet-education.pdf