4

Is there any git command to set a remote repository for a branch (perfectly for all) in local repository without pushing commits form that local to the remote?

in short all what I want to get can be done by using flag --all: git push --all

optionally with setting upstreams -u as well: git push --all -u

but I don't want to push any commits.

The desired result is just to set link between local and remote repository for git push so if you git push in the future you don't need to specify the remote and also may skip --all option.

Jimmix
  • 5,644
  • 6
  • 44
  • 71
  • 1
    Possible duplicate of [Make an existing Git branch track a remote branch?](https://stackoverflow.com/questions/520650/make-an-existing-git-branch-track-a-remote-branch) – phd Oct 04 '18 at 23:19
  • https://stackoverflow.com/search?q=%5Bgit%5D+set+remote – phd Oct 04 '18 at 23:19

1 Answers1

4

For one branch, see the question phd linked-to, i.e., Make an existing Git branch track a remote branch?

To do this for some set of branches, use a loop. To do it for all branches, use git for-each-ref to loop over all branches, as in this sh / bash looping construct:

git for-each-ref --format='%(refname:short)' |
    while read name; do
        git branch --set-upstream-to=origin/$name $name
    done

(which is all one line, really, just broken into more readable lines here).

This assumes you want the upstream name for each name to be origin/name. If not, substitute appropriately. Note that this will override any existing upstream set for each such name, or fail if no upstream with that name exists yet.

If origin/xyzzy does not exist yet, you cannot set branch xyzzy to have origin/xyzzy as its upstream. This is perfectly logical. However, it may not be what you want.

You can override Git's intelligence about this by going below the level of git branch, replacing the git branch --set-upstream-to with raw git config operations:

git for-each-ref --format='%(refname:short)' |
    while read name; do
        git config branch.$name.remote origin
        git config branch.$name.merge refs/heads/$name
    done

This assumes that your remote.origin.fetch setting is +refs/heads/*:refs/remotes/origin/*. If it is not, you should already know what you are doing and how to modify the above loop.

Note that setting the upstream to a nonexistent remote-tracking name will make Git believe that the name used to exist and is now gone: git branch -vv will report the upstream as "gone". Git is not very smart about causality, so it thinks that if the upstream is set to a nonexistent branch, the causal sequence must have been:

  1. upstream exists
  2. branch's upstream is set to existing upstream
  3. upstream is deleted, causing branch's upstream to be set inappropriately

when in fact the actual cause was that you set the upstream inappropriately on purpose, in anticipation of the setting becoming appropriate in the future. So ignore the "gone" annotation.

torek
  • 448,244
  • 59
  • 642
  • 775
  • second loop example worked for me but I needed to change the line: `git config branch.$name.merge $name` to: `git config branch.$name.merge refs/heads/$name` – Jimmix Oct 05 '18 at 21:02
  • *"If origin/xyzzy does not exist yet, you cannot set branch xyzzy to have origin/xyzzy as its upstream."* - it does not seem logical to me. I expect this command to actually create `origin/xyzzy`. Or are you implying only that `origin/xyzzy` is supposed to be created in advance? Which command needs to be used in this case? – user7860670 Apr 15 '22 at 15:00
  • @user7860670: `git branch --set-upstream-to` won't create the upstream name. It must exist. So yes, I am implying that `origin/xyzzy` needs to be created in advance (of the set-upstream-to step). The problem is that the command that creates it is `git push`, or more specifically, a Git operation that sees that `xyzzy` has been created on `origin` and therefore creates `origin/xyzzy` locally. But that operation is normally your own `git push`. – torek Apr 15 '22 at 23:55
  • It's like saying you have to join the club to be a member of it before you can petition the club to be a member of the club: you want to set the upstream to make `git push` work with no options, but to do that, you must first make `git push` work (with no options?) before you can make `git push` work with no options. – torek Apr 15 '22 at 23:55
  • Well, any solution that requires `git push` is not really helpful in the context of this question. – user7860670 Apr 16 '22 at 12:24
  • @user7860670: indeed, that's the point here: there is a Catch-22. You must first run `git push` to create the upstream so that you can set the upstream so that you can run `git push`. The *simple* solution is one `git push -u origin HEAD` run, which gets you *out* of the Catch-22 situation, after which you're no longer in it. But the OP asked for a way to set the upstream of N existing branches with (apparently) existing upstreams, so that's what I answered. – torek Apr 16 '22 at 13:55
  • If the upstreams *don't* exist, the complicated solution is to use two separate `git config` commands, which I showed as the alternative. That works but has the side effect that some Git commands will gripe that the upstream is "gone". One must simply live with that side effect. – torek Apr 16 '22 at 13:57