loading...
Cover image for Dotfiles - Git Config with Aliases

Dotfiles - Git Config with Aliases

michaelcurrin profile image Mike Updated on ・5 min read

Setting up git aliases and core settings in your git config

See my full Git config on GitHub.

Most of this post is focused on git aliases, with bit of core settings at the end.

If you are new to git aliases, see this dev.to post.

Setup aliases

Here is the format - add aliases to your ~/.gitconfig file, which uses TOML format.

[alias]
    MY_ALIAS = "GIT_COMMAND"
    MY_ALIAS = "! MY SHELL COMMAND"

Git aliases

Here is a sample based on my Git config file.

[alias]
    st = "status -s -b"
    c = "commit"

    # --all
    # --verbose
    br = "branch -a -v"

    co = "checkout"
    cb = "checkout -b"

    # Short hash, relative date and message.
    logd = "log --pretty='%C(yellow)%h %C(cyan)%ar %Creset%s'"

    # --graph:
    #     Draw a text-based graphical representation of the commit history on
    #     the left hand side of the output.
    # --decorate:
    #     Print out the ref names of any commits that are shown. Defaults to
    #     short optionm such that the name prefixes refs/heads/, refs/tags/ and
    #     refs/remotes/ will not be printed.
    lol = "log --graph --decorate --oneline"

Notes on the config:

  • You must use double quotes if using spaces in an alias value, otherwise you'll get command not found error.
  • You don't need to reload your terminal to get changes - git aliases are evaluated fresh each time you run a git command.
  • There is a Better Toml extension for VS Code which helps handle this and I find this works better than using the Gitconfig extension and file type in VS Code.

I am going to demonstrate the usage and output of some of my git aliases next.

View git aliases

As promised from the previous part of this series, here is how to list all aliases that are available.

$ git alias
st = status -s -b
c = commit
br = branch -a -v
co = checkout
...

Git status

View a summary of your git status.

$ git st
## master...origin/master
 M configs/shell/.aliases
 M configs/shell/.commonrc
 M configs/shell/.gitignore

That is much quieter than:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   configs/shell/.aliases
        modified:   configs/shell/.commonrc
        modified:   configs/shell/.gitignore

no changes added to commit (use "git add" and/or "git commit -a")

Git log oneline

Show one line for each item in git log output.

$ git lol
* 9103ed0 (HEAD -> master, origin/master, origin/HEAD) Update .gitconfig
* 8a40fdb docs: Add comment
* f750060 feat: Update .gitconfig

Sync local and remote commits and tags

Do a pull with a --rebase flag, then push.

$ git sync
Already up to date.
Current branch master is up to date.
Everything up-to-date

It is safe to rebase here, since the commits are unpushed. Also, if there have been no local commits, the pull --rebase will just act as a plain pull without rewriting commits.

If you want to fetch all tags and then push all tags, do this:

$ git sync-tags
Enumerating objects: 1, done.
...
 * [new tag]         v0.8.0 -> v0.8.0

If you want to combine both of the above aliases to pull commits and tags and then push commits and tags, do this:

$ git sync-all

Here is the setup for that last one:

[alias]
  sync-all = "! git pull --rebase && git push --progress && git push --tags"

The --progress flag makes pushing quiet but not so quiet as --quiet.

I recently discovered this for pushing a commit and tags together:

$ git push --follow-tags

However, it only pushes tags at the current commit, so if you've tagged any older commits then those won't get pushed.

So to ensure all tags get pushes, I went back to this approach:

$ git push --progress && git push -tags

View git tags

Show git tags using semver ordering, with higher tag numbers first.

$ git tags
v0.7.0
v0.6.0
v0.5.0

Note that git tag with no arguments also lists tags. But, will typically show older tags first and the ordering seems weird sometimes as it sorts by text and not by meaning (so 11.0.0 and 1.0.0 could appear side by side).

So my alias ensures the recent ones are first and they are sorted using semvar.

Git aliases that invoke the shell

Use an exclamation mark ! at the start of a command to use a shell command without it going through git.

This means you can use cd and find for example. And chain shell commands using && or ||.

[alias]
    # Go to root of git repo.
    grt = "! cd $(git rev-parse --show-toplevel)"

    # Sync local and remote commits.
    sync = "! git pull --rebase && git push"
    # Sync local and remote tags.
    sync-tags = "! git fetch --tags && git push --tags"
    # Sync local and remote commits and tags.
    sync-all = "! git pull --rebase && git push --progress && git push --tags"

Use arguments in a shell alias

Note that you can even reference arguments. Use can use $1 and $2 and so on for the position arguments for the aliases.

My use-case for this is limited but here is one that use this approach. Note that the check at the start shows a message if the count of arguments is not equal to one.

[alias]
    clone-https = "! [ $# -ne 1 ] && echo 'Args: USERNAME/REPO_NAME' || git clone https://github.com/$1.git"

Sample usage:

$ git clone-https
Args: USERNAME/REPO_NAME

$ git clone-https MichaelCurrin/dotfiles
Cloning into 'MichaelCurrin/dotfiles'...

Instead of using the forward slash, you could expect two arguments and then substitute them as $1/$2.git.

It is also possible to create a shell function instead and to define and invoke it as part of the alias, but I found using the syntax I've covered above cleaner.

Configure global ignore file

The last part I want to mention on my Git Config part is not an alias but a core setting.

This tells git to use a global git ignore file, if it exists. Note you must used double quotes so that ~ gets expanded.

[core]
    editor = "nano"
    excludesfile = "~/.gitignore"

You must create this file yourself, which I'll cover in the next post.

Multiple git configs

By the way, I discovered you have have multiple git configs and set it up so that a folder of work repos all use that.

See this post by @jma.

This sounds great as I use a different email for my work projects and I don't have to remember to set it locally on each repo.

Share

If you any handy git aliases, please share them in the comments.

Next

Carry on to Part 5.

Posted on by:

michaelcurrin profile

Mike

@michaelcurrin

I'm a self-taught dev focused on websites and Python development. My friends call me the "Data Genie". When I get bored, I find tech to read about, write about and build things with.

Discussion

pic
Editor guide
 
[alias]
    make = "! make"
    test = "! run_test"
    exclude = "! vim .git/info/exclude"
 

Thanks for sharing.

What are the usecases of running those like git make ARG vs just running make ARG?

Regarding tests I usually have a test command in Makefile so I can run make test. Then it is also accessible to anyone with the repo its Makefile and they don't need my aliases setup.

What kind if content do you put in your exclude files?

 

git make change directory to root of the project first.
I put my own working configuration into exclude, testing directories, swap files, Makefile in project without Makefile, tagfiles, etc. There should also be IDE files inside, but many developers do weeds .gitignore, which is common to all.

Oh yes I forgot about that in git.

If you don't want to run exclude each time you can add those IDE files to your global gitignore file

dev.to/michaelcurrin/dotfiles-glob...

Yes, I know the global gitignore and I use it, but something is differ in different projects.