git fetch + git merge origin/master vs git pull origin/master

一个人想着一个人 提交于 2021-02-11 16:55:45

问题


I thought git pull was like a git fetch + git merge. Being in branchA, I always do a git fetch and then a git merge origin/master. But today, being in a branchA, I tried git pull origin/master and it didn't work but doing a git pull origin master worked. Any thoughts?

Extra question, if an updated origin/master and the online version of master are the same, why bother to have origin/master, wouldn't it be more convenient to always work with the online version that is always updated, releasing us from the burden to alway be git fetching?


回答1:


I thought git pull was like a git fetch + git merge.

It is. However, the syntax one uses with git pull does not match the syntax one uses with pretty much every other Git command. This is due to history: git pull predates a number of improvements made in Git between pre-1.5 and post-1.6 Git versions. (Note that Git is now at version 2.26, so this is truly ancient history, dating back to 2005 or so. The oldest versions of Git that people still seem to use today are in the version 1.7 range—but when you run git pull, you're harking back to the pre-stone-age, dinosaur Git 1.5 era.)

[but] I tried git pull origin/master and it didn't work [while] git pull origin master worked

That is because this is the special syntax just for git pull.

Read the git pull documentation carefully for exceptions (of which there are plenty), but in general, most of the arguments you pass to git pull, git pull passes to git fetch. Just as you would not run:

git fetch origin/master      # wrong

you cannot run

git pull origin/master       # also wrong: this runs git fetch origin/master

You can, however, run:

git fetch origin master

Here origin is a remote and master is a refspec (see the git fetch documentation for more about remotes and refspecs). This specifically limits your git fetch operation to fetch only commits new-to-you that are on their master, so as to update only your origin/master.1

After the fetch is complete, pull runs merge, or if you so specify, rebase, on some set of branch-head commits.2 The general idea here—which goes back to that pre-Git-1.6 history I mentioned—is that, having fetched some commit(s) from some other Git, you now wish to incorporate those commits into your current branch.

There was a time, in early Git, when the entire concept of remote did not exist, and hence there were no remote-tracking names: there was no origin at all, hence no origin/master. It was therefore important to incorporate their commits immediately, lest your Git run a garbage collection pass and remove the new commits you obtained.

In the post-1.6 era—i.e., since 2006 or so—it's been safe to collect the commits and let them sit there for a while, while you look them over, think about them, or even ignore them entirely for a while. The remote name origin introduced the remote-tracking names, such as origin/master, which retains those commits indefinitely. There is no longer any need for a mad rush of shoving those commits into one of your own branches, in order to prevent them from being removed.

The bottom line is: If you find git pull convenient, use it. If not, don't. Remember that the arguments you'll use, if you use arguments, are unique to it. It's just a combination of git fetch, plus an immediate second command to incorporate some fetched commits into the current branch. I find this in-convenient, most of the time: I like to inspect the fetched commits first. If you don't use git pull, you'll name the incoming commits with remote-tracking names like origin/master, but if you do use git pull, you can't use these names in the git pull command itself, because it is being compatible with ancient times when these names did not exist.


1This kind of git fetch will update your origin/master in any modern Git, but in Git versions before 1.8.4, it will leave origin/master un-updated.

2The commits chosen as arguments to merge or rebase are those from references that you specifically named on the command line, if you named any. Otherwise, the (single) commit chosen as an argument is the one corresponding to the upstream setting of the current branch.

In some corner cases, git pull runs something other than merge or rebase as its second command. The most interesting of these special cases is pulling into a completely empty repository: here, neither git merge nor git rebase will do anything, so git pull essentially just runs git checkout instead. This one special case obviously happens only once in any given repository.



来源:https://stackoverflow.com/questions/61211167/git-fetch-git-merge-origin-master-vs-git-pull-origin-master

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!