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
?
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
).
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.