If you find git confusing, I created this little cheat sheet! Please, note that I voluntary skipped the basic commands like git commit
, git pull/push
... This cheat sheet is intended for an "advanced" usage of git.
🧭 Navigation - Go to the previous branch
git checkout -
🔍 Get the history
# Log in one line
git log --oneline
# Retrieve all commits by message
# Here all commit that contain 'homepage'
git log --all --grep='homepage'
# Retrieve all commit by author
git log --author="Maxence"
🙈Ooops #1: I reseted an unwanted commit. How to rollback?
# Get everything you did
git reflog
# then reset to the desired commit (i.e. HEAD@{4})
git reset HEAD@{4}
# ...or...
git reset --hard <commit-sha1>
For more detail about this command, I wrote this post.
🤦♀️Ooops #2: I mixed-up with my local repo. How to clean it?
git fetch origin
git checkout master
git reset --hard origin/master
# You're now up-to-date with master!
🕵🏻♂️Difference between my branch and master
git diff master..my-branch
✔ Custom commits
# Edit last commit
git commit --amend -m "A better message"
# Add something to the last commit without writing message again
git add . && git commit --amend --no-edit
# empty commit - can be useful to re-trigger CI build...
git commit --allow-empty -m "chore: re-trigger build"
If you don't know what to put in your commit messages, I wrote a post about conventional commits.
♻️ Squash commits
Let say I want to rebase the last 3 commits:
git rebase -i HEAD~3
- Leave the first "pick" and replace the rest by "
squash
" (or "s
") - Tidy up the commit message and save (
:wq
in vi).
🎯Fixup
Let say I want to add something in the commit fed14a4c
git add .
git commit --fixup HEAD~1
# or replace HEAD~1 by the commit hash (fed14a4c)
git rebase -i HEAD~3 --autosquash
# save&quit the file (:wq in VI)
🕹Execute command on each commit when rebasing
For massives features, you might end up with a branch with a few commits inside. And then tests are failing and you want to identify the "guilty commit". You can use rebase --exec
to execute a command on each commit of the history.
# Will run "npm test" command on the last 3 commit ❤️
git rebase HEAD~3 --exec "npm run test"
🦋Stash
Because it's not all about git stash
and git stash pop
;)
# save all tracked files
git stash save "your message"
# list your stashes
git stash list
# retrieve stash and delete
git stash apply stash@{1}
git stash drop stash@{1}
# ... or in 1 command
git stash pop stash@{1}
🗑 Clean
# remove branches that no longer exist on remote
git fetch -p
# remove all branch that contains "greenkeeper"
git fetch -p && git branch --remote | fgrep greenkeeper | sed 's/^.\{9\}//' | xargs git push origin --delete
🐙 GitHub = Git
+ Hub
I use Hub as a wrapper for git. To enable it you've to set hub as an alias for git (alias git='hub'
).
# Open browser and go to the repository url (GitHub only)
git browse
Other commands are available here.
🦄 Bonus: my favourite git aliases
alias g='git'
alias glog='git log --oneline --decorate --graph'
alias gst='git status'
alias gp='git push'
alias ga='git add'
alias gc='git commit -v'
# 🤘
alias yolo='git push --force'
# useful for daily stand-up
git-standup() {
AUTHOR=${AUTHOR:="`git config user.name`"}
since=yesterday
if [[ $(date +%u) == 1 ]] ; then
since="2 days ago"
fi
git log --all --since "$since" --oneline --author="$AUTHOR"
}
And you, what's your favourite git command?
Thank you for taking the time to read this post. I hope you found it useful! If you liked it, please give it a ❤️ or a 🦄! Also, feel free to comment or ask questions in the section below or on Twitter @_maxpou :)
Originally published on maxpou.fr.
Top comments (58)
My favorite git utility is "reuse recorded resolution"
git rerere
. Sometimes if you have multiple parallel branches and try to merge or rebase between them, you get the same conflict multiple times.git rerere
records your resolution and then just automatically applies it, if you encounter the same conflict again.And it's pretty much set it and forget it because it completely works autonomously in the background. git-scm.com/docs/git-rerere
I never heard about this one until now. It looks very handy! I'll give a try on my next conflict!
Thanks for sharing 👍
Found here: github.com/nicksp/dotfiles/blob/ma...
this config is... massive!!! 😯
Awesome article... congrats :)
My favourite and most used Git alias:
The
gwip
commits everything with the message--wip-- [skip ci]
. By everything I mean untracked files, changes not staged for commit, and changes already staged for commit.The
gunwip
revertsgwip
, with the caveat that changes already staged for commit will become changes not staged for commit.I use it to save my work until I am ready to create a proper commit.
Having
[skip ci]
in the commit message tell the Continuous Integration pipeline to ignore the commit.This is a great idea! This functionality should probably be included within git.
One idea that comes to my mind how you could complicate this (read: make it work "completely"). You could extend the script to open all the staged files and add a comment to the top of the file. Something like:
--staged--
. Then, when you "unwip", it can read that comment and stage/unstage files as needed, while also removing that comment.It already is, in a way.
If you do a
git stash -u
, it will create a commit for you that includes staged, unstaged and untracked files, and it knows which files were staged and which ones weren't. If you wanted to keep the changes that were stashed as they were, you can issue agit stash apply
immediately after (useapply
to keep the stash, orpop
to discard it after applying it).This is amazing! Thank you!
Git never seizes to amaze me for its unlimited functionality.
For applying the stash, you need add
--index
as in:git stash apply --index
. This will restore the index (staged/unstaged files) along with the file changes.Awesome cheat sheet, really. Learned quite a few things despite being quite advanced with git already.
I prefer my version of
git lg
(logs), which also displays the date of each commit in a neat format:gist.github.com/Vadorequest/9d1f86...
* f0d6b49 - wip (3 hours ago) <Me>
Love this one 😍 Thanks!!! Will update my dotfiles right now!
Excellent guide! I like the idea of git-standup. ☕
For alias, to work even with mistyping, I also use:
Also, one thing that was really useful for me is the meta repository of Matt Walters, so I can avoid git submodule and subtree to work with multiple repositories.
Nice article. I got to learn about a few things I didn't know about git before.
By the way
git save
is deprecated now, you should rather go bygit push -m
.And for the last section about git aliases, since I'm using bash I get all these aliases and much more when I install oh-my-bash.
Hmm.. where did I wrote a command with
git save
?About the aliases, I have something similar: Oh-my-zsh. But I extract those aliases in my personal dotfiles so I can get them everywhere I need them :)
Sorry, it seems I completely messed up the comment. I meant to use
git stash push -m
instead ofgit stash save
, as the latter is deprecated.you completely right Mohammed! Thanks for pointing this out :)
Improved version:
interesting! 😃
Nice post Maxence.
If you need to overwrite the master from the dev branch any time:
git branch -f master dev_branch [will rewrite local master branch.]
git push remote +dev_branch:master [will rewrite remote branch.]
Nice article, thank you for sharing. Want to some more favorite aliases to the list.
The
git -standup()
one in nice. Can you please explain a bit on how to use it?I love the
git-standup
function!