简体   繁体   中英

Git Fetch with Source:Destination vs Git Pull

From all the questions regarding differences between fetch and pull, the answer is that fetch will update your copy of the remote and not merge anything into your local branch. But if you use the fetch command with source:destination say "git fetch origin development:development" it will update both the remote copy and the local copy. So what is the difference in this case between a pull and a fetch?

But if you use the fetch command with source:destination say "git fetch origin development:development" it will update both the remote copy and the local copy.

This isn't quite true.

One exception (which we can perhaps discount) occurs with Git versions predating 1.8.4, where git fetch origin development:development simply fails to update refs/remotes/origin/development entirely. However, git fetch origin development also fails to update refs/remotes/origin/development here. That's why I suggest discounting old versions of Git: they still behave the same way with respect to fetch-and-merge, as it were. (Well, that, and they're really quite old.)

The more important exception, though, is when a fast-forward operation—a "fast forward merge", as git merge will claim it to be—is not possible or is prohibited through the merge.ff and/or pull.ff configuration variables or command line options. This gets into the difference between a fast-forward and an actual merge.

When you have git pull run fetch-and-merge, the second Git command is, or is equivalent to, running an actual git merge command. This command will:

  • find the merge base commit(s) between HEAD and the merge target(s);
  • then, consider whether a merge is possible and/or whether a fast-forward operation is possible and allowed.

A fast forward is possible and allowed when:

  • the merge base is HEAD ;
  • there's one other commit to merge and HEAD is an ancestor of that commit; and
  • neither the command line nor the configuration prohibit fast-forwarding.

In this case—the fast-forward possible-and-allowed case, that is— git merge will do that fast forward instead of merging, and in this case, git fetch origin development:development would also fast-forward the local branch name development .

But if a merge is possible, but fast-forwarding is prohibited or impossible, the git merge will do a real merge, while the git fetch origin development:development will simply fail to fast-forward the name development . So here, the two commands differ. Of course if you want your pulls always to fast-forward, and have configured pull.ff to only for instance, we're back to the operations being the same.

Well, almost . There's still one more difference: git pull 's git merge will fast-forward the current branch (only), but git fetch origin development:development will fail if development is the current branch. So you have to be on some other branch. There is a way to make git fetch fast-forward the current branch (supply the --update-head-ok flag) but if you do this, you must use extreme caution as the updated branch name has not affected the index and work-tree, unlike a git merge driven fast-forward operation.

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