简体   繁体   中英

git alias including checkout and pull + rebase with params

What am I doing wrong here? Suppose I'm in branch "one" and wanna switch to master and execute a pull --rebase.

The alias I used was:

git config --global alias.cpr "!git checkout $1 && git pull --rebase $2 $1"

Thanks

Start with something much simpler:

$ git config --global alias.showme "!echo checkout $1 and pullrebase $2 $1"

Now run it:

$ git showme master origin
checkout and pullrebase master origin

Whoops, where's master after the word checkout ? What is our alias set to anyway?

$ git config --get alias.showme
!echo checkout  and pullrebase  

(you can't really tell here but there are two spaces after and pullrebase above, which is another clue).

The problem here is not in fact Git itself, but rather the shell:

$ echo "I said $1 and $2"
I said  and 

The shell has eaten $1 and $2 here, replacing them with what they are set to, which is nothing. Let's put something in them:

$ set hello there
$ echo "I said $1 and $2"
I said hello and there

If you want to put a literal $1 and $2 into your alias, you must protect them from the shell when you run the git config command. Or, simpler, you can use git config --global --edit to run your favorite editor—the same one Git uses for other things, that you set when you set up Git—on your global configuration.

Let's say you've fixed your alias, eg, run:

$ git config --global alias.showme '!echo checkout $1 and pullrebase $2 $1'

(note the use of single quotes here, instead of double quotes: single quotes are "stronger" and protect against $ expansion). Now let's run that alias again:

$ git showme master origin
checkout master and pullrebase origin master master origin

Wait, why is it stuttering, saying master master ?

Uh oh, now what?

Now we have a Git problem.

The behavior of git alias is that $ gets expanded before running the alias, and then all the parameters are added after the alias expansion. So the alias first expands to:

echo checkout master and pullrebase origin master

and then all the arguments ( master origin ) are added to the end!

In this particular case, you could avoid the problem by leaving out the final $2 $1 , but you would have to change the order of parameters you give to the alias.

Instead, you can use a different trick: make the alias run a shell function , and supply all the parameters as arguments to the shell function. That is, make the alias expand to:

!f() { cmd $args && cmd $args && ...; }; f

after which Git will insert the arguments as arguments to f .

Note all the extra semi-colons here (before and after the close-brace). Some shells have slightly different syntax rules but in general you need to end the statement sequence in order to close the function, then end the function definition before running the function.

There's one remaining problem, which is that Git will expand each $ . This means that the alias itself must contain \\$ . If you need quotes as well, getting all this into the .gitconfig file is a pain. The best way is generally to use your editor ( git config --global --edit ).

Beware of git pull

This has nothing to do with the question, but watch out for git pull 's bad behaviors. If you run git pull origin master branch2 it will do an "octopus merge", which is almost certainly something you don't want. It's easy to recover, but the best thing is just to avoid git pull entirely. All git pull does is run git fetch followed by another Git command. With --rebase , the other Git command is git rebase . If you are already making your own alias, just run git fetch <args> && git rebase <args> in your alias, and avoid all the weirdness that git pull can do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM