Command
-
push-f/--force- Ensure remote repo is the same as the local repo
- How to use git push force the right way (opens in a new tab)
Notes
-
Pull
-
merging
git pull --mergeIf you pull remote changes with the flag --merge, which is also the default, then your local changes are merged with the remote changes. This results in a merge commit that points to the latest local commit and the latest remote commit.
-
-
Merge
-
Make sure there was no uncommitted changes before the merge started
-
A
fast-forwardmerge can only be done when the most recent commit on the target branch is an ancestor in the source branch (i.e. the commit at the tip of the receiving branch (main) must appear somewhere in the branch providing the new commits (feat/x) ).
-
-
Log
git log-
--onelineDisplay
login compactone-lineformat -
--branchesSpecifiy the
branch,current branchif omitted
-
Revisions
-
<rev>Include commits that are reachable from
<rev>(i.e.<rev>and its ancestors). -
^<rev>Exclude commits that are reachable from
<rev>(i.e.<rev>and its ancestors). -
<rev1>..<rev2>Include commits that are reachable from
<rev2>but exclude those that are reachable from<rev1>. When either<rev1>or<rev2>is omitted, it defaults toHEAD. -
<rev1>...<rev2>Include commits that are reachable from either
<rev1>or<rev2>but exclude those that are reachable from both. When either<rev1>or<rev2>is omitted, it defaults toHEAD. -
<rev>^@, e.g.HEAD^@A suffix
^followed by@is the same as listing all parents of<rev>(meaning, include anything reachable from its parents, but not the commit itself). -
<rev>^!, e.g.HEAD^!A suffix
^followed by!is the same as giving commit<rev>and all its parents prefixed with^to exclude them (and their ancestors). -
<rev>^-<n>, e.g.HEAD^-,HEAD^-2Equivalent to
<rev>^<n>..<rev>, with<n> = 1if not given.
G H I J
\ / \ /
D E F
\ | / \
\ | / |
\|/ |
B C
\ /
\ /
AA = = A^0
B = A^ = A^1 = A~1
C = = A^2
D = A^^ = A^1^1 = A~2
E = B^2 = A^^2
F = B^3 = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2 = B^^2 = A^^^2 = A~2^2
I = F^ = B^3^ = A^^3^
J = F^2 = B^3^2 = A^^3^2| Args | Expanded arguments | Selected commits |
|---|---|---|
| D | G H D | |
| D F | G H I J D F | |
| ^G D | H D | |
| ^D B | E I J F B | |
| ^D B C | E I J F B C | |
| C | I J F C | |
| B..C | ^B C | C |
| B...C | B ^F C | G H D E B C |
| B^- | B^..B | |
| ^B^1 B | E I J F B | |
| C^@ | C^1 | |
| F | I J F | |
| B^@ | B^1 B^2 B^3 | |
| D E F | D G H E F I J | |
| C^! | C ^C^@ | |
| C ^C^1 | ||
| C ^F | C | |
| B^! | B ^B^@ | |
| B ^B^1 ^B^2 ^B^3 | ||
| B ^D ^E ^F | B | |
| F^! D | F ^I ^J D | G H D F |
Dotted Range Notations
-
<rev1>..<rev2>Examples
-
g log origin..HEADWhat did I do since I forked from the
originbranch? -
g log HEAD..originWhat did the
origindo since I forked from them?
-
URL
-
SSH
git@gitlab.com:cq-devops/playground-git.gitor
ssh://git@gitlab.com/cq-devops/playground-git.git -
HTTP
https://gitlab.com/cq-devops/playground-git.git
Cheatsheet
Run Git command from another directory
git -C $directory $commandCheck out a specific commit to the working copy in detached HEAD state
-
Notes
- To keep the changes in
detached HEADstate: switching to a new branch - To discard the changes in
detached HEADstate: switching to an existing branch
- To keep the changes in
-
git checkout $COMMIT_IDor
-
git switch -d $COMMIT_ID(>= 2.23)
Return to HEAD of previous branch
git switch -` (**>= 2.23**) or a specific branch `git switch <branch_name>Update and replace the most recent commit
-
git commit --amend (--no-edit / -m <message>)-
--amendThe latest
commitwill be replaced by thenew commit. -
--no-editKeep the same
commit message, or provide a newcommit messagewith-m
-
Commit changes of a specific file or directory
g commit -m $commit_message -- $file / $dirLog
Show log of a single file
g log --follow -- $fileShows the log of the specified file in spite of renaming
Show log of a single file with diff
g log --follow -p -- $fileShows the log of the specified file in spite of renaming, with diff
Show log of most recent commits
g log -$number# e.g.
g log -10Show log of changed file names
g log --name-statusShow summary of log
g shortlogShow log of commits in hash
g log --format=%HShow logs with full hashes
g log --no-abbrevSearch log by commit message matching the specified regex
g log --grep="$regex"Search log by patch text matching the specified regex
List files with contents matching the given regex
g log -E -G${regex} --name-status --oneline --source --allg log -E -G${regex} --name-status --oneline --source --all | egrep 'refs/.+?\s|$'Search log by date
# e.g.
g log --since 2022-01-01 --until 2022-01-31Search log by author
g log --author $authorUse a regex to match author name(s)
Diff the log between local branch and another branch
Recommended before git pull
-
Show diff of each commit
git log HEAD..origin/master -
Show commits only
git log --oneline --graph HEAD..origin/master -
Show a single combined diff of all commits
git diff HEAD..origin/master -
Resources
List all revisions of a file
g rev-list --all -- $fileList all files changed in a commit
g show --oneline --name-status $commit_idView a file of a specific commit
g show $commit_id:$fileSearch file contents by regex pattern in all tracked files
g grep --heading --break -C2 -E "$regex" $(g log -G'direnv' --format=%H)Use Git log to narrow down commits range
Change remote repo URL
g remote -vg remote set-url origin $urlStash
-
Work as a stack,
FILO -
Default stash name
when no
<stash>is given,stash@{0}is assumed, otherwise<stash>must be a reference of the formstash@{<revision>}.
Save working copy changes to a new stash with the default name
g stash (push)Show existing stashed changes
g stash listShow the changes recorded in the stash entry as a diffstat
-
as
diffstatg stash show -
as
diffg stash show -p
Remove everything in the stash
g stash clearApply the most recent pushed stashed changes to working copy
g stash (pop | apply)Interactively select each hunk (consecutive lines of change in a file) you want to stash
g stash push --patchPatch
Create a patch file for staged changes
g diff --staged > $patch_fileCreate a patch file for a single commit relative to the current branch
g format-patch -1 $commit_idCreate one patch file for each commit relative to a specific branch
g format-patch $branch_nameCreate one patch file for all commits consolidated relative to a specific branch
g format-patch $branch_name --stdout > $patch_fileApply a patch file without committing
g apply $patch_fileApply a patch file and commit
g am $patch_fileAbort on supplying commit message in Vim
Use :cq to make Vim quit with an error code, and Git will abort the operation.
Revert committed changes
g revert $commit_idGit will apply changes opposite to the specified commit to reverse the effects by creating a new commit.
More useful on a public branch, as it doesn't alter the existing commit history.
Delete unversioned directories and files
To remove directories
g clean -fdTo remove ignored files
g clean -fXTo remove ignored and non-ignored files
g clean -fxTo remove ignored and non-ignored files interactively
g clean -idDry run cleaning unversioned files
g clean -nRemove a file from repository but keeping local copy
g rm --cached $fileMerge
Check if a fast-foward merge is possible
g merge-base --is-ancestor $(gb --show-current) $branch_to_merge_fromMerge a topic branch with squashed commits
g merge --squash $branch_name- All changes will be staged in working copy under the current
branch, therefore still need to be committed. - Use
git commitwill put all commit messages in the draft for editing.
Dry-run a merge
-
git merge --no-commit --no-ff <branch>or
gm --no-commit --no-ff <branch>Changes stay in index
-
git merge --abortReset the index
Choose a merge strategy when merging
-
g merge -s <strategy> -X <option> --no-commit <branch-name>Choose changes from target branch over local branch
-
g merge -s ours --no-commit <branch-name>Favor ours
-
g merge -X theirs --no-commit <branch-name>Favor theirs
Abort a merge process
git reset --mergegit merge --abort
Merge an upstream repository into your fork
-
Retrieve a local copy of upstream branch to be merged
g remote add upstream <upstream_git_url> g fetch upstream <branch_source> -
Switch to the branch you want to merge the changes into
g switch <branch_target> -
Merge the changes from upstream repo
g merge upstream/<branch_source>or
g merge '@{u}'
Rebase
Rebase a branch interactively
g rebase -i $branchRebase while pulling changes
g pull --rebaseIf you pull remote changes with the flag --rebase, then your local changes are reapplied on top of the remote changes.
Link an existing local Git repo to a remote repo
g remote add origin $repo_url
g push -f origin $branchMake a local branch track a remote branch
g branch -u origin/$remote_branch $local_branchor
g branch --set-upstream-to=origin/$remote_branch $local_branchConvert a short hash to a full hash
g rev-parse $short_hashShow the name of current branch
g rev-parse --abbrev-ref HEADor 2.22+
g branch --show-currentShow the absolute path of the top-level directory of the working tree
g rev-parse --show-toplevelCreate a tag with message
g tag -a $tag -m $messageIf message omitted, editor will be opened to input message.
Create a local branch with the specified remote tracking branch
g checkout -b $new_branch $remote_branchor
g checkout -b $new_branch $remote_branchCreate a new local branch and switch to it
The new branch is based on the current branch.
g switch -c $new_branchShow remote tracking branches for all local branches
g branch -vvClone a branch or tag
git clone --depth 1 --branch $tag_name $repo_urlusing --depth 1 to only download one commit
Push local tag(s) to remote
git push $remote $tagPush the specified local tag
or
git push --tagsPush all local tags
Fetch a single tag from remote
g fetch $remote tag $tag_name --no-tagsFetch all tags from remote
g fetch [$remote] --tagsDelete a remote tag
g push --delete $remote $tag_nameDelete all remote tags
g push --delete $remote $(git tag -l)List all local tags
g tag -lList local tags with pattern
g tag -l "$regex"e.g. g tag -l "v*"
Checkout a local tag
g checkout $tag_nameCheckout a local tag into a branch
g checkout tags/$tag_name -b $branch_nameDelete a local tag
g tag -d $tag_nameDelete all local tags
g tag -d $(git tag -l)Delete a local branch
g branch -d $localBranchNameDelete a remote branch
g push origin --delete $remoteBranchNameUnstage a file and keep local changes
git restore --staged <FILE>git reset <FILE>
Unstage a file and discard local changes
g restore $fileDelete all commits since the specified commit
git reset --hard $commit_id- Discard all changes (both uncommited and committed) since the specified
COMMIT ID - can be used to reset
unfinished merge
Delete the last commit from history
git reset --hard HEAD~1Restore a historic version of a file
git restore --source $commit_id $fileRecover a lost commit
-
git reflogThis command displays all
HEADchanges, so you can get any lostCOMMIT_ID.And use the
COMMIT_IDto recover any changes bygit restore -s <COMMIT_ID> <DIR/FILE>
Config
List config (globally or locally)
git config -l [--global|--local]
Display config variables
man git config
List of items that can be configured
Display remote repo URL
git config remote.origin.urlTurn off oh-my-zsh repo status
git config --add oh-my-zsh.hide-status 1
git config --add oh-my-zsh.hide-dirty 1List all aliases
git config --get-regexp aliasCheck if a file is being ignored
-
git check-ignore -v <file1 [file2]...>If ignored, output would show the matched pattern with line number in Git ignore file.
If not ignored, no output would display.
Ignore a directory
-
Add the directory name to
.gitignorefollowed by a slashdirectory-to-ignore/
List versioned files
git ls-files -v $file [file2...]List modified files
git ls-files -m <file1 [file2]...>
Rename a local branch
# Switch to the branch to be renamed
git switch $branch_to_be_renamed
# Rename the branch
git branch -m $new_branch_nameCherry-pick commits from another branch
-
Use case
-
Production bug fix
- Use
mainbranch to check in bug fix - Then use
cherry-pickto merge commits back tofeaturebranch (pullis ideally better, but in practicemainbranch often has other commits that you don't want.)
- Use
-
-
Resources
Update from remote upstream branch
git stash
git pull --rebase
git stash popSubmodule
Submodule - Add a submodule
g submodule add -b $branch $repo_URL $submodule_dir-
Submodule added before
fatal: A git directory for 'playground-messaging-http-simulator' is found locally with remote(s): origin git@gitlab.com:playground-messaging/playground-messaging-http-simulator.git If you want to reuse this local git directory instead of cloning again from git@gitlab.com:playground-messaging/playground-messaging-http-simulator.git use the '--force' option. If the local git directory is not the correct repo or you are unsure what this means choose another name with the '--name' option.In this case, use
--forceoption, you will see something similar to:Reactivating local git directory for submodule 'playground-messaging-http-simulator'
Submodule - Remove a submodule
-
Steps
-
Remove submodule directory under parent repo directory:
rm -rf $submodule_dir -
Remove submodule directory from index:
g rm --cached $submodule_dir -
Remove submodule directory under
.gitdirectory:rm -rf .git/modules/$submodule_name -
Remove submodule entry with name
$submodule_namefrom file.git/config -
Remove submodule entry with name
$submodule_namefrom file.gitmodulesunder parent repo directory.
-
-
Stack Overflow - Git submodule add: "a git directory is found locally" issue (opens in a new tab)
Submodule - Commit changes when a submodule is changed
- When a submodule has new commits, the parent repo needs to be updated with the latest commit.
LFS
LFS - Initialize Git LFS
- This will update Git hooks to track large files
- Handling Large Files with LFS | Learn Git Ebook (CLI Edition) (opens in a new tab)
git lfs installLFS - Track files of a pattern with Git LFS
- Always execute the "track" command from the root of your project. The reason for this advice is that patterns are relative to the folder in which you ran the command.
- The
$file_patternis case sensitive. - The
$file_patternwill be added to.gitattributesfile. - Use
git lfs statusandgit lfs ls-filesto verify if the pattern is working as expected.
git lfs track $file_patternLFS - List all files tracked by Git LFS
# Under a repo
git lfs ls-files -adls# Output
filepath: media/image/photo/select1.JPG
size: 5456070
checkout: true
download: true
oid: sha256 817b09f77dc45ba9351daab70e5735a41af7d3b60524690ab314e0c1ac069cf3
version: https://git-lfs.github.com/spec/v1LFS - Get Git LFS environment
git lfs env# Output
git-lfs/3.2.0 (GitHub; linux amd64; go 1.19.4)
git version 2.43.0
Endpoint=https://gitlab.com/some-repo.git/info/lfs (auth=none)
SSH=git@gitlab.com:some-repo.git
LocalWorkingDir=/local-repo-dir
LocalGitDir=/local-repo-dir/.git
LocalGitStorageDir=/local-repo-dir/.git
LocalMediaDir=/local-repo-dir/.git/lfs/objects
LocalReferenceDirs=
TempDir=/local-repo-dir/.git/lfs/tmp
ConcurrentTransfers=8
TusTransfers=false
BasicTransfersOnly=false
SkipDownloadErrors=false
FetchRecentAlways=false
FetchRecentRefsDays=7
FetchRecentCommitsDays=0
FetchRecentRefsIncludeRemotes=true
PruneOffsetDays=3
PruneVerifyRemoteAlways=false
PruneRemoteName=origin
LfsStorageDir=/local-repo-dir/.git/lfs
AccessDownload=none
AccessUpload=none
DownloadTransfers=basic,lfs-standalone-file,ssh
UploadTransfers=basic,lfs-standalone-file,ssh
GIT_EXEC_PATH=/git-installation/libexec/git-core
git config filter.lfs.process = "git-lfs filter-process"
git config filter.lfs.smudge = "git-lfs smudge -- %f"
git config filter.lfs.clean = "git-lfs clean -- %f"LFS - Get Git LFS status
# Under a repo
g lfs status# Output
On branch develop
Objects to be pushed to origin/develop:
Objects to be committed:
.gitattributes (Git: ed72c32 -> Git: fbc4da5)
media/image/photo/_DSC9253.JPG (LFS: b737ca9)
Objects not staged for commit:Tooling
git-filter-repo
-
Install
GitHub - newren/git-filter-repo: Quickly rewrite git repository history (opens in a new tab)
It's a Python package, and needs to be installed first.
Completely remove a file from LFS
-
Run
git filter-repo --path ${path/to/file} --invert-paths -
Sync up with remote repo
GitHub CLI
List all Gists
gh gist list -L 50Edit a Gist locally
gh gist edit $IDAdd a local file to a Gist
gh gist edit $ID -a $fileCreate a Gist based on a local file
gh gist create -f $file_name_on_Gist -d $description < $local_filegit-extras
Gitflow
-
developbranch to include allfeaturedevelopmentmain->develop -
Release preparation
develop->release -
New feature
develop->feature -
Bug fix
main->hotfix -
When a
featureis complete, it is merged intodevelop -
When the
releasebranch is done, it is merged intodevelopandmain -
Once the
hotfixis completehotfix=>develophotfix=>main
Commit message management
Message format
[$Tag] $SubjectMessage tags
| Tag | Description |
|---|---|
feat | A new feature |
fix | A bug fix |
docs | Documentation only changes |
style | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) |
refactor | A code change that neither fixes a bug nor adds a feature |
perf | A code change that improves performance |
test | Adding missing tests or correcting existing tests |
plumbing | Changes to the build process or auxiliary tools and libraries such as documentation generation |
Resources
-
Commit Often, Perfect Later, Publish Once: Git Best Practices (opens in a new tab)
-
Atlassian Git Tutorial - Gitflow Workflow (opens in a new tab)
-
Git Config