GEspinha GEspinha - 1 month ago 4
Git Question

multiple commands in git alias is not working

I have the following code in my

.gitconfig
file:

[alias]
john = "!f(){ git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done; git fetch --all; git pull --all; };f"


Which is basically creating an
alias
for pulling every branch on the remote server. But is constantly trowing an error. Can someone help me understand what is going wrong, I've tried dissecting the command, but I can't find what is going wrong.

Answer

You need to escape embedded double quotes with backslashes. For instance:

[alias]
    next = "!f() { id=$(git rev-list --reverse --ancestry-path ..master | head -1); test -n \"$id\" && git checkout $id || echo 'no more commits'; }; f"

(which I actually have commented out since hardcoding master is bogus: this is a leftover from this answer).

You can also wrap long lines with backslash-newline:

    next = "!f() { \
        id=$(git rev-list --reverse --ancestry-path ..master | head -1); \
        test -n \"$id\" && git checkout $id || echo 'no more commits'; }; f"

(untested, but should work).

All that said, this is wrong:

Which is basically creating an alias for pulling every branch on the remote server.

Your sample alias attempts to create a new local branch for each remote-tracking branch (which is fine as far as it goes, but not possible in full generality, e.g., if you have both refs/remotes/origin/zorg and refs/remotes/evil/zorg, you cannot have local branch zorg track both remote-tracking branches). (For scripting purposes, it's better to use git for-each-ref here, but the existing loop should work well enough for your purposes.)

But, then you run git fetch --all, which means fetch from all remotes (fetch defaults to fetching from the "current" remote, which is pretty loosely defined as "the current branch's remote, or origin if the current branch has no remote set). Once the fetch finishes, you run git pull --all, which passes --all to git fetch again, then attempts to merge (or rebase) the current branch based on its configured remote and merge settings.

This therefore updates at most one of the branches you created in the while loop.

To merge-or-rebase each local branch, you need to loop over the local branches (again, preferably using git for-each-ref).

Comments