DEV Community

Cover image for Dotfiles - Git Config with Aliases
Michael Currin
Michael Currin

Posted on • Edited on

Dotfiles - Git Config with Aliases

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"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
...
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Here is the setup for that last one:

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

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Sample usage:

$ git clone-https
Args: USERNAME/REPO_NAME

$ git clone-https MichaelCurrin/dotfiles
Cloning into 'MichaelCurrin/dotfiles'...
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (5)

Collapse
 
vlasales profile image
Vlastimil Pospichal
[alias]
    make = "! make"
    test = "! run_test"
    exclude = "! vim .git/info/exclude"
Enter fullscreen mode Exit fullscreen mode
Collapse
 
michaelcurrin profile image
Michael Currin

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?

Collapse
 
vlasales profile image
Vlastimil Pospichal

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.

Thread Thread
 
michaelcurrin profile image
Michael Currin

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...

Thread Thread
 
vlasales profile image
Vlastimil Pospichal

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