How do I create a custom git/bash script?

Viewed 359

I'd like to make it so that if I type git recent in my terminal, it actually runs: git reflog | egrep -io "moving from ([^[:space:]]+)" | awk '{ print $3 }' | awk ' !x[$0]++' | egrep -v '^[a-f0-9]{40}$' | head -n5 giving me the 5 most recent git branches I've checked out to.

Bonus points: I'd like to add an argument, so that if I type git recent 20 it runs: git reflog | egrep -io "moving from ([^[:space:]]+)" | awk '{ print $3 }' | awk ' !x[$0]++' | egrep -v '^[a-f0-9]{40}$' | head -n20 giving me the 20 most recent git branches I've checked out to.

Also, any readings/tutorials series to recommend in to better understand how this script works, and how to write custom bash scripts? Thanks.

4 Answers

If you create a script, accessible from your path, and name it : git-foo, then :

git foo arg1 arg2 ...

will invoke that script, with arguments.

It's the advised way if fitting your command on one single line for a git alias becomes too complicated.

A possible alternative with a simple git alias :

$ git config --global alias.recent '!f() { for i in $(seq 1 $1); do git name-rev --name-only --exclude=refs/tags/\* @{-$i}; done; }; f'

$ git recent 3
some-branch
other-branch
yet-another-branch

You can also sort it easily with git recent <n> | sort -u if needed.

egrep | awk | awk | egrep | head is really an anti-pattern that should almost certainly just be done with a single awk, but that's not terribly relevant here. You can easily write a function to wrap git and do what you want. Put the following in your bash startup scripts:

git() {
        case "$1" in
        recent)
                command git reflog | egrep -io "moving from ([^[:space:]]+)" |
                        awk '{ print $3 }' | awk ' !x[$0]++' | egrep -v '^[a-f0-9]{40}$' | head -n${2-5}
        ;;
        *)
                command git "$@"
        ;;
        esac
}

Now, if the first argument to the function is recent, the reflog pipe will be executed, using the 2nd argument as the number of lines to show (defaulting to 5). If the first argument is not recent, the args will be passed unchanged to git.

are you aware of git aliases ?

Permanent aliases are stored in your .gitconfig file, usually in your home directory.

You can edit this file and append:

[alias]
    recent = "!git reflog | egrep -io 'moving from ([^[:space:]]+)' | awk '{ print $3 }' | awk ' !x[$0]++' | egrep -v '^[a-f0-9]{40}$' | head -n5"

You would use it like so git recent


What does ! mean ?

As you may have noticed the !. I will explain what's what. A standard alias such as: cm = commit -m will when used go from git cm to git commit -m.

But as a matter of fact you can tell git to replace the whole line. If I were to write cm = !commit -m when used the command would go from git cm to commit -m

That's what the ! does.


Bonus point

It is way more ugly but still worth checking:

[alias] 
    bonus = "!f() { \
             git reflog | egrep -io 'moving from ([^[:space:]]+)' | awk '{ print $3 }' | awk ' !x[$0]++' | egrep -v '^[a-f0-9]{40}$' | head -n$1; \
             }; f"

You would use it like so git bonus <number of branches>

Related