8

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:

[alias]
    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
[alias]
    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)

2

3 Answers 3

7

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"' -

(dead link) 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
foo

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

2
  • P.S. Why the dash at the end?
    – Hari Honor
    Sep 11, 2013 at 16:58
  • @HariKaramSingh: Edited the answer with more information. Sep 11, 2013 at 18:29
5

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
0

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 http://nvie.com/posts/a-successful-git-branching-model/ + https://superuser.com/questions/435744/git-alias-for-merging-current-branch-with-master
        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 http://nvie.com/posts/a-successful-git-branching-model/
    

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

You must log in to answer this question.

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