Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to create a git alias that merges the currently checked out branch into the master branch. Specifically I'd want to quickly get my master branch get up to speed with what I'm working on. I've got the following:

    co = checkout
    ff = !git co master && git merge work && git co work

However I'd like the alias to know which branch it was on and get back to it. I tried adding $1 but unfortunately I get a error on the last checkout in the alias:

# with
    co = checkout
    ff = !git co master && git merge $1 && git co $1

> git ff work
Switched to branch 'master'
Already up-to-date.
error: pathspec 'work' did not match any file(s) known to git.

Anyone knows why it does this? (I'm on a Mac by the way)

share|improve this question
Related topic on stackoverflow though it doesn't answer the issue that I have. – Spoike Jun 12 '12 at 12:15
up vote 5 down vote accepted

If you're going to use positional parameters in git aliases, be sure to specify sh -c. The following worked for me locally:

ff = !sh -c 'git checkout master && git merge "$1" && git checkout "$1"' -

The "why" relates to the way git parses the alias commands and is summed up in this gmane thread.

The - at the end of the command signals sh that option processing is finished. From man sh:

A -- signals the end of options and disables further option processing. Any arguments after the -- are treated as filenames and arguments. An argument of - is equivalent to --.

If it weren't present, it would introduce a bug in the alias, by treating $1 as an option on the sh command instead of as a positional argument. Consider this trivial example:

$ sh -c 'echo $1' foo          # equivalent to 'echo' without argument

$ sh -c 'echo $1' - foo        # will pass 'foo' to the string as $1

In the first case, 'foo' was consumed by sh as an option. In the second, it's correctly interpreted as $1 on the string.

share|improve this answer
Works like a charm, thanks! – Spoike Jun 13 '12 at 14:06
P.S. Why the dash at the end? – Hari Karam Singh Sep 11 '13 at 16:58
@HariKaramSingh: Edited the answer with more information. – Christopher Sep 11 '13 at 18:29

Here's a version with which you don't need to specify the current branch and can choose any target branch:

merge-into = !sh -c '_CURRENT_BRANCH=$(git symbolic-ref --short HEAD) && git checkout $1 && git merge $_CURRENT_BRANCH && git checkout $_CURRENT_BRANCH' -

Usage (from my-branch):

git merge-into master
share|improve this answer

Thanks to the answers in this thread, I updated some aliases I've been using:

  • git fold <target> [source] -- merge the <target> branch into current (preserving history), optionally specifying a source branch other than current; mff is another shorthand

    fold = !sh -c '_CURRB=$(git symbolic-ref --short HEAD) && git checkout $1 && git merge --no-ff ${2-$_CURRB} -e' - ; per suggestion +
        mff = "!git fold"
  • git foldback <target> [source] -- same as fold, but switches back to the source (current) branch

    foldback = !sh -c '_CURRB=$(git symbolic-ref --short HEAD) && git fold $1 ${2-$_CURRB} && git checkout ${2-$_CURRB}' -
  • git fuse <target> [source] -- same as fold, but deletes the source branch (i.e. when you're done working on a feature)

    fuse = !sh -c '_CURRB=$(git symbolic-ref --short HEAD) && git fold $1 $2 && git branch -d ${2-$_CURRB}' - ; per suggestion

I don't know enough about shell stuff to know a better way to reuse _CURRB; any suggestions?

share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .