loading...

My Personal Git Tricks Cheatsheet

antjanus profile image Antonin Januska Updated on ・4 min read

Besides the "basic" commands of Git, everyone has their own little Git tricks they use. I wanted to quickly write a list of my own which I tend to alias in my .gitconfig. Scroll to the bottom to see some fun git related commands that run outside of git! :)

Quick amend

I often forget to commit a file, or leave a console.log in. I absolutely hate doing commits like removed console.log. So instead, I add the file as if I was going to make a commit and run:

git commit --amend --reuse-message HEAD

Which will add the file to the last commit and reuse the old commit message. I alias this one as git amend for quickfixes

NOTE Based on feedback below, it's also possible to do git commit --amend --no-edit for the same effect.

Rebase on top of origin/master

Older branches often fall behind pretty far, so far that I have to get up to speed to eliminate build errors, ci errors, or just resolve conflicts. My favorite is to do the following:

git fetch origin # fetch latest origin
git rebase origin/master

This way, I'm stacking my current branch commits on top of the latest version of master!

Last commit

Sometimes, the git log gets overwhelming. Due to my frequent use of the aforementioned amend command, i tend to want to view just the last commit in my git log:

git log -1

checkout older version of a file (like a lock file!)

Occasionally, I screw up a file unrelated to my branch. Mostly, that happens with lock files (mix.lock, package-lock.json, etc.). Rather than reverting a commit which probably contained a bunch of other stuff, I just "reset" the file back to an older version

git checkout hash-goes-here mix.lock

And then I can commit the fix!

cherry-pick

An underrated command that I occasionally use. When a branch gets stale, it's sometimes easier to just get the stuff you really need from it rather than try to get the entire branch up to speed. A good example, for me, have been branches that involve UI/backend code that is no longer necessary. In that case, I might want to cherry pick only certain commits from the branch

git cherry-pick hash-goes-here

This will magically bring that commit over to the branch you're on. You can also do a list!

git cherry-pick first-hash second-hash third-hash

You can also do a range

git cherry-pick first-hash..last-hash

The reflog

This is such a power-user feature that I rarely use it. I mean, once a year! But it's good to know about it. Sometimes, I lose commits. I delete a branch or reset or amend a commit I didn't mean to mess up.

In those situations, it's good to know reflog exists. It's not a log of individual commits for the branch you're on, it's a log of all of your commits -- even ones that were on dead branches. However, the log gets emptied from time to time (pruned) so that only relevant information stays.

git reflog

The command returns a log and what's useful is cherry-picking or rebasing on top of a commit. Very powerful when you pipe into grep.

Bash command aliases

Aside from git commands, I like to also use some fun bash aliases to help my workflow

Current branch

To get the name of the current branch, I have this alias:

alias git-branch="git branch | sed -n -e 's/^\* \(.*\)/\1/p'"

When I run git-branch or run $(git-branch) in another command, I'll get the name of the current branch I'm on.

NOTE Based on feedback in the comments, I switched this over to git symbolic-ref --short HEAD which works just as well but you can actually read it.

Track upstream branch

While I'm sure this is doable in the .gitconfig, I've yet to figure out how. When I run the first push on a new branch, I always get asked to setup the branch for upstream tracking. Here's my alias for that:

alias git-up="git branch | sed -n -e 's/^\* \(.*\)/\1/p' | xargs git push -u origin "

Now when I run git-up, I push my current branch and setup upstream tracking!

Feedback

Based on some of the very helpful feedback in the comments, I made some adjustments to what I'm using.

Current branch

It looks like there are a bunch of new ways to get the current branch name. If you scroll up, you'll see that I've used a crazy sed parsing command to get the branch name.

Here's my new alternative:

alias git-branch="git symbolic-ref --short HEAD"

And it seems to work exactly as you'd expect!

Posted on by:

Discussion

pic
Editor guide
 

Track upstream branch
alias git-up="git branch | sed -n -e 's/^\* \(.*\)/\1/p' | xargs git push -u origin "

Assuming that you have set your git-branch alias already, you could simplify this as:

alias git-up="git push -u origin \$(git-branch)"

EDIT: escaped $ to prevent running the alias on definition, thanks @darlanalves

 

Git assumes the current branch implicitely, so the following also works:

alias git-up="git push -u origin"

Even better is to use a git alias for this:

git config --global alias.up 'push -u origin'

so you can use it like $ git up.

If you think you need to explicitly specify the branch anyway you can define an alias like this:

git config --global alias.up '!git push -u $(git-branch)'
 

Nice! Thank you for the tips!

The git up alias is perfect.

 

Not specifying the branch still gives me a Fatal: The current branch has no upstream. Any ideas why?

Did you specify the -u flag?

Yep, I copied and pasted this exactly
git config --global alias.up 'push -u origin'

yeah, looks like I have the same issue!

Ok, after some digging I got an alias to work. I have no idea why it works when nothing else I tried would but here it is anyway. I think it is best to paste the following into your .git-config file directly:

up = "!git push -u origin `git symbolic-ref --short HEAD`"

or if you have git 2.22

up = "!git push -u origin `git branch --show-current`"

I figured this out mostly by messing around with this Stack Overflow answer: stackoverflow.com/a/30529511/9770212

 

the problem is that the git-branch got evaluated when I started my terminal. This is in zsh. :/

I'd immediately get "not a git repository" message.

 

maybe a function would work?

function gitUp() {
  git push -u origin $(git-branch)
}

Oh, you're right... an alias would be immediately evaluated.
Using a function is the way to go.

it kind of tripped me up! I was expecting it to evaluate when invoked, just like a function.

Yeah, it may not be intuitive at first... but is really useful to be able to rely on both behaviors (evaluate on definition or when run).
If you wanted to use other aliases within an alias you have to start playing around with eval (which I don't really recommend). Like:

alias testingEval="eval 'git-branch'"

But things get messy pretty quickly... I pretty much use alias for super simple things or functions when I need something a bit longer that could use some extra variables, or to use parameters, or runtime expansion.

btw, I use zsh too :) ... I use prezto and got some configs online if you want to take a look
github.com/ivanalejandro0/prezto/b...

I get why it works like that and I'm ok with it :) It really just surprised me but then again, I don't do a lot of bash scripting.

The key to it is just escape the $ char in an alias.

alias git-up="git push -u origin \$(git-branch)"

Oh, cool. I didn't know about that, thanks.
I've edited my comment escaping the $.

 

I like this kind of articles, we can get some ideas.

From your examples, I had the feeling that you're not sure how to include arguments or bash commands into aliases. You might be interested in one my articles:

 

I do know. And the comments taught me a good deal but I don't like adding bash commands to git aliases since I use git on non Linux machines

 

Sorry then. How come you use sed and xargs in your aliases? Or you want to maintain only one .gitconfig and push all the rest to OS-specific setenvs?

That's it!

I write completely different aliases for Powershell but I get to still use identical git aliases

Have you considered using Git BASH on windows?

yep, quickly dismissed it. It's not worth it plus Powershell is just so damned good!

 

Nice post!

For the "get the name of the current branch" there's a git plumbing command that can help you get the current branch name reliably without the text manipulation:

alias git-branch="git rev-parse --abbrev-ref HEAD"

I tend to keep this one as part of my git aliases:

git config alias.current "rev-parse --abbrev-ref HEAD"

Here's a quick write-up if you're interested!

 

On the current branch alias, don't forget git branch --show-current with Git 2.22: stackoverflow.com/a/55088865/6309.

I used it in stackoverflow.com/a/56713414/6309

 

also if you've got git > 2 this works

git status --porcelain=v2 --untracked-file=no --branch \
| grep branch.head \
| cut -d ' ' -f 3

 

looks like I'm still a little behind on versions. I'm on v2.17.x

Neat tip though, I'll have to remember to come back and change my rc files to use this :)

 

I HAD NO IDEA. This is awesome! Thank you! :)

 

Current branch
alias git-branch="git branch | sed -n -e 's/^\* \(.*\)/\1/p'"

My approach to get the current branch is this:

alias gcb='git symbolic-ref --short HEAD'

(gcb to remind me of Git Current Branch)

I like it more because it uses only git and I don't depend on piping through another app.

 

Quick amend
git commit --amend --reuse-message HEAD

My approach for this is git commit --amend --no-edit

 

I like that better. 👍

 

I am afraid to do git cherry-pick without the -n parameter because cherry-picking automatically commits after picking the changes. Most of the time I want to review the changes and commit them manually. So I do:

git cherry-pick -n HASH
 

ooh, i wasn't aware of the dry run. I tend to not care because I can always do an interactive rebase and delete those commits.

 

Why use shell aliases for something that's git specific? You can just use git aliases.

Instead of:

alias git-branch="git branch | sed -n -e 's/^\* \(.*\)/\1/p'"

Do:


git config --global alias.this-branch '!'"git branch | sed -n 's/^\* \(.*\)/\1/p'"

Now, from within any repo, you can run git this-branch, and you didn't have to add anything to your shell, and if you switch shells, it will continue to work.

 

That's pretty cool! I basically just learned about that from people on this post

 

Git aliases

# ~/.gitconfig
[alias]
    spull = "!git stash && git pull --rebase && git stash pop"
    spush = "!git stash && git pull --rebase && git push && git stash pop"
    pushf = push --force-with-lease
    ameno = commit --amend --no-edit
    anarchy = "!git add . && git ameno && git pushf"

System aliases

# ~/.bashrc, ~/.zshrc, ...
alias cdg='cd $(git rev-parse --show-toplevel)'
 

Great tips, Antonin!

I've been using similar tricks in my daily flow... And they definitely help productivity!
I've added them to a repo so I can share between my machines and with other devs :)

github.com/darlanalves/faster-git

 

Thank you for the nice writeup Antonin! I'll definitively take over a few :)

Might not be totally related, but in order to not be able to commit things that are not to be committed, we're using (husky)[github.com/typicode/husky] and a pretty strict linting :)

 

We actually use husky too!!

 

great! also take a look to this: ohshitgit.com/

 

You can simply do git push -u origin HEAD and not have to mess around with evaluating the branch name.

 

Thanks for sharing!! I have a question about git log -1. Why don't you use git show instead? Does it have any benefits?

 

Your trick git reflog saved my today working. Thanks :)

 

That's awesome! I'm happy to hear that!

 

I just do this to get the current branch:
git branch | grep '*'

 
 

I had no idea about cherry-picking a list of commits! This is a game-changer!

 

You should also have *.log in your .gitignore

And *.sw[a-p] if you have vim friends.