How to make an alias for git subtree push command with repository and refspec

566 views Asked by At

I want to define a shortcut (alias) for the following command:

    git subtree push --prefix=_site [email protected]:mertnuhoglu/blog_datascience.git gh-pages

I want to be able to use the shortcut such that I won't need to specify the repository name. Even when using it in different repos.

Is this possible? How can I do this?

1

There are 1 answers

5
nils On BEST ANSWER

In the home directory of your user

  1. Windows: C:\Users\<user-name> (or in git-bash: /c/Users/<user-name>)
  2. Linux: /home/<user-name>
  3. Mac: /Users/<user-name>

create or open a file called .bashrc and append the following line

alias gsp="git subtree push --prefix=_site [email protected]:mertnuhoglu/blog_datascience.git"

Then open a new (git-)bash and the alias gsp should be available.

UPDATE

This update describes a more general approach, which should work for multiple subtrees and for any git repository (that has been configured accordingly).

The requested alias would require a mechanism to automatically infer

  1. the prefix
  2. the name of the remote or its address, and,
  3. the remote branch

for each subtree.

As far as I know git-subtree only stores the hash of a commit in the remote repository that has been referenced (and possibly its history), but it does not store the address of that remote, as can be seen in the output of git-log of a toy example:

*   1ffc070 Merge commit '7a9390a29011dad36b2def6b0d0881b0361875e8' as 'bar.st'
|\  
| * 7a9390a Squashed 'bar.st/' content from commit 10e3347
* 429987f - Added foo.

So, there goes the easy solution.

But what about storing the required information from the enumeration above in a config file, e.g. .gitsubtrees alongside each repository? That file uses a simple file format:

# <prefix>;<remote address/name>;<remote branch>
bar.st:../bar:master
_site;[email protected]:mertnuhoglu/blog_datascience.git;master
# ...

Then add the following function to your .bashrc:

function gsp
{
    # Config file for subtrees
    #
    # Format:
    # <prefix>;<remote address>;<remote branch>
    # # Lines starting with '#' will be ignored
    GIT_SUBTREE_FILE="$PWD/.gitsubtrees"

    if [ ! -f $GIT_SUBTREE_FILE ]; then
        echo "Nothing to do - file <`basename $GIT_SUBTREE_FILE`> does not exist."
        return
    fi

    OLD_IFS=$IFS
    IFS=$'\n'
    for LINE in $(cat $GIT_SUBTREE_FILE); do

        # Skip lines starting with '#'.
        if [[ $LINE = \#* ]]; then
            continue
        fi

        # Parse the current line.
        PREFIX=`echo $LINE | cut -d';' -f 1`
        REMOTE=`echo $LINE | cut -d';' -f 2`
        BRANCH=`echo $LINE | cut -d';' -f 3`

        # Push to the remote.
        echo "git subtree push --prefix=$PREFIX $REMOTE $BRANCH"
        git subtree push --prefix=$PREFIX $REMOTE $BRANCH
    done
}

If, for some git repository, the config file .gitsubtrees does not exist, gsp won't do anything otherwise it will print the command it executes and the corresponding output.

$ gsp
git subtree push --prefix=bar.st ../bar master
git push using:  ../bar master
-n 1/       3 (0)
-n 2/       3 (1)
-n 3/       3 (1)

Note: for readability the code of gsp neglects sanity checks and also doesn't handle exceptions. If git subtree push fails your back to manual labour.