简体   繁体   中英

Why behaviour of git fetch origin +refs/heads/master:refs/remotes/origin/mymaster and git fetch origin master:mymaster is different?

Why behaviour of

git fetch origin +refs/heads/master:refs/remotes/origin/mymaster

and

git fetch origin master:mymaster

is different?

In my observation in case of

git fetch origin +refs/heads/master:refs/remotes/origin/mymaster

it was creating a remote-tracking branch "mymaster".

On the other case of

git fetch origin master:mymaster

it was creating a local branch "mymaster".

Well git fetch will fast-forward your local reference, and create it if it doesn't exist. So:

git fetch origin master:mymaster

creates a branch mymaster locally if it doesn't exist and

git fetch origin +refs/heads/master:refs/remotes/origin/mymaster

creates a branch remotes/origin/mymaster locally if it doesn't exist.

The syntax being src:dst , where src is remote and dst local.

Read the gitrevisions manual page (run git help revisions ) and look for the revision specification " <refname> ". Here's an excerpt from that bit of documentation:

<refname> , eg master , heads/master , refs/heads/master

A symbolic ref name. Eg master typically means the commit object referenced by refs/heads/master . If you happen to have both heads/master and tags/master , you can explicitly say heads/master to tell Git which one you mean. When ambiguous, a <refname> is disambiguated by taking the first match in the following rules:

  1. If $GIT_DIR/<refname> exists, that is what you mean (this is usually useful only for HEAD , FETCH_HEAD , ORIG_HEAD , MERGE_HEAD and CHERRY_PICK_HEAD );
  2. otherwise, refs/<refname> if it exists;
  3. otherwise, refs/tags/<refname> if it exists;
  4. otherwise, refs/heads/<refname> if it exists;
  5. otherwise, refs/remotes/<refname> if it exists;
  6. otherwise, refs/remotes/<refname>/HEAD if it exists.

So what you observed in your experiments is that when you have used unadorned mybranch as the target ref name, from the point of view of Git that was a relative ref name, and hence Git used the precedence rules to resolve it, and resolved it to refs/heads/mymaster .

When you used refs/remotes/origin/mymaster , you supplied Git with the absolute ref name, so there was nothing to resolve and Git used it directly.

A point of interest: it's perfectly OK to have a local branch containing a slash in its name, and it will still be relative when specified without that refs/... anchor. That is, you can do git branch foo/bar and when you will later call git log foo/bar Git will use the rules above to resolve foo/bar into an absolute ref name (and will supposedly end up with refs/heads/foo/bar ).

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