Git Hacks
Last Updated: 2019-03-13
Git is by the far the de-facto standard for version control, but out of box it lacks a lot of tools that make it easier to work with. I’ve built quite a range of aliases and separate scripts to help with every day use. Here’s a collection. of some of them.
Use Most instead of Less or More
Not specifically Git related, but I would recommend using
most as your default pager instead of more or
less. It shows syntax highlighting, which is more than handy. You can install
it using the package manager of your distro if you’re running Linux, or via
Homebrew on macOS. Just install it, and set your $PAGER
environment variable to its path.
$ echo "export PAGER='/usr/local/bin/most'" >> ~/.bash_profile
$ export PAGER='/usr/local/bin/most'
$ echo $PAGER
/usr/local/bin/most
Useful Git Aliases
Quick discard all changes on a file
$ git config --global alias.discard 'checkout --'
$ git discard <file>
Un-stage a file.
$ git config --global alias.unstage 'reset HEAD --'
$ git unstage <file>
Show last commit log
$ git config --global alias.last 'log -1 HEAD'
$ git last
Show all commits, in a nice format
$ git config --global alias.log-all 'log --oneline --decorate --graph --all'
$ git log-all
Show all commits, but more verbose that log-all.
$ git config --global alias.log-full 'log --pretty=medium --decorate --all --stat'
$ git log-full
Turning On/Off GPG Signing
Like a good GitHub user, I always sign my commits. However, there’s a lot of
work repos that I don’t need to / want to sign. So I find myself turning on
and off GPG signing. To help with this, I’ve written two Bash aliases that get
loaded in my .bash_profile
. That way, I can run git-sign
to turn on
signing, and git-nosign
to turn it off.
alias git-sign='git config --global commit.gpgsign true'
alias git-nosign='git config --global commit.gpgsign false'
Git References Script
There’s a number of repositories that have multiple refs, and it’s a bit hard
to keep track of what state each is at. I can run the git log-all
or git
log-full
from above, but I also wrote a Bash script that uses the for-each-ref
command to print them all out, with some basic information.
#!/bin/bash
# File: git-refs
printf "\e[1;34m${PWD}\e[0m"
fmt='
%(color:bold cyan)%(refname:short)%(color:reset):
Commit: %(color:yellow)%(objectname)%(color:reset)
Date: %(committerdate:format:%Y-%m-%d %H:%M:%S)
Committer: %(committername) %(committeremail)'
git for-each-ref --sort=-committerdate --format="$fmt" refs
Sample output:
$ git-refs
/path/to/test
origin/master:
Commit: c1814782ddfcc5492ca9beff44801584313025b3
Date: 2018-10-15 19:48:53
Committer: Chris Pedro <chris@thepedros.com>
origin/HEAD:
Commit: c1814782ddfcc5492ca9beff44801584313025b3
Date: 2018-10-15 19:48:53
Committer: Chris Pedro <chris@thepedros.com>
GitLab/master:
Commit: c1814782ddfcc5492ca9beff44801584313025b3
Date: 2018-10-15 19:48:53
Committer: Chris Pedro <chris@thepedros.com>
GitHub/master:
Commit: c1814782ddfcc5492ca9beff44801584313025b3
Date: 2018-10-15 19:48:53
Committer: Chris Pedro <chris@thepedros.com>
master:
Commit: c1814782ddfcc5492ca9beff44801584313025b3
Date: 2018-10-15 19:48:53
Committer: Chris Pedro <chris@thepedros.com>
Setting Up Multiple Remote Repos
Normally, you’ll only have one remote repo, but this may not always be the
case. For example, I push all my personal public repos to GitHub and GitLab,
because why keep all your eggs in one basket? I could just use git remote
commands to set up multiple remote repos, but I found it way easier to just
edit the .git/config
file in the repo itself. Doing this also allows you to
set two URLs for the ‘origin’ repo, which means anytime you push or pull to
‘origin’, you’ll be pushing or pulling to or from both URLs. This means, for
example, you simply do a git push origin master
and have the repo synced up
to all remote repos in one go.
First, backup up your config in case anything goes wrong, then open
.git/config
using your favourite text editor, and add all the remote repos
using the format below. The <REMOTE>
on the first and last line much match.
[remote "<REMOTE>"]
url = <REMOTE_URL>
fetch = +refs/heads/*:refs/remotes/<REMOTE>/*
Next, edit the [remote "origin"]
directive and simply add the same url =
line you did above. You can specify as many URLs as you wish all will be used
when doing a push.
As an example, below is the config I use for this projects repo. As you can
see, I have a “GitHub” and “GitLab” remote repo named, and both URLs are under
“origin”. Each time I run git push origin master
, both remote repos are
updated. Also, I can pull or push to each individually by running git pull
GitHub master
or git pull GitLab master
for example. Also, running git
fetch --all
will run a ‘fetch’ on both remote repos.
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:cpedro/cpedro.github.io.git
url = git@gitlab.com:cpedro/cpedro.github.io.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[remote "GitLab"]
url = git@gitlab.com:cpedro/cpedro.github.io.git
fetch = +refs/heads/*:refs/remotes/GitLab/*
[remote "GitHub"]
url = git@github.com:cpedro/cpedro.github.io.git
fetch = +refs/heads/*:refs/remotes/GitHub/*