Git Cheatsheet


compare / diff / log


Display diff between staging area and working directory :

git diff --staged

Show the difference between current branch and its remote counterpart :

git fetch
git log ..origin/$(git rev-parse --abbrev-ref HEAD)

Show commit logs with paths that moved :

git log --stat -M

RIGHT OUTER JOIN branch_A ON branch_B :

git log branch_B..branch_A
git diff branch_B...branch_A

Show the commit log with orphaned commits (which might have been orphaned by a rebase) :

git log --graph --reflog


Interact with remote


Add a git URL as a remote named [alias] :

git remote add [alias] [URL]

Publish a local branch onto the remote, and set it as upstream :

git push --set-upstream origin [branch]

Delete a remote branch :

git push origin --delete [branch]

Print detailed info of the remote & its content (remotes branches for example) :

git remote show origin

Update remote URL :

git remote set-url origin [new-url]


Interact with upstream


List all remotes & upstreams :

git remote -v

Add an upstream, from a fork for example :

git remote add upstream https://github.com/[user]/[project].git

Pull from upstream :

git fetch upstream
git merge upstream/[branch]


revert / reset / rm


Unstage all files staged since last commit :

git reset HEAD^

Rollback to commit <ref>, but keep everything modified as unstaged files :

git reset <ref>

Unstage <file> :

git reset HEAD <file>

Rollack the last N commits :

# Hard : All changes will be lost
git reset --hard [HEAD~N]

# Soft : All changes are staged
git reset --soft [HEAD~N]

# Mixed : All changes are kept but not staged
git reset --mixed [HEAD~N]

Interactive rollback. Pick an action for each rollbacked commit 1-by-1 :

git reset --keep

Overwrite the current branch with the version stored on the server (forced pull) :

git fetch --all
git branch backup-master
git reset --hard origin/master

Reset the date (and author) after an interactive rebase :

git commit --amend --reset-author

Dry-run of rm :

rm -n


Deep purge


In case you uploaded a password or API key

Install git-filter-repo :

apt-get install git-filter-repo

Move the current project, and clone a fresh copy.
If not a clean clone, add --force to the git-filter-repo command instead.

mv -r ./<project> ./<project_backup>
git clone <remote_url> 

The critical part :

git-filter-repo --path <file_to_remove> --invert-paths --force

# Variant : filtering only certain branches & tags
git-filter-repo --path <file_to_remove> --invert-paths --force --refs main develop $(git tag -l)

Re-set the remote_url, and force-push the new repo :

git remote add origin <remote_url>
git push --set-upstream origin main -f


Stash


Save current non-staged edits into the stash :

git stash push (-m [message])

List stash entries :

git stash show [<id>]
git stash list

Apply a stash entry to the working directory & staging area :

# Entry will be removed from stash
git stash pop [<id>]
# Entry will stay in stash
git stash apply [<id>]

Apply a stash entry on top of its parent commit, on a new branch :

git stash branch <new_branch> [<id>]

Delete a stash entry :

# single entry
git stash drop [<id>]
# wipe all entries
git stash clear


Tags


Add a tag to the current commit :

git tag <tag_name>
git tag -m "<description>" <tag_name>

# Push to remote
git push --tags

Tag an older commit / other branch :

git tag <tag_name> <ref>

Delete a tag :

git tag --delete <tag_name>
git push --delete origin <tag_name>

Overwrite (= move) an existing tag :

git tag -f <tag_name> <ref>


Misc


Move file in the working directory and in the index

git mv <file>

Quickly find which commit introduced a bug

git bisect (command)

Find on which commit file was deleted

git rev-list HEAD -n 1 -- <file>

Merge 2 repos together

cd <A>
git remote add -f <B> <B_url>
git merge <B>/master

mkdir <B>

dir -exclude B | %{git mv $_.Name <B>}
# or
git mv <file> <B>