问题
I made two changes to my remote repository
in GitHub
, by adding a new file
and deleting a old file
(by using the Web interface of GitHub
). when I do :
git fetch origin master
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 5 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
From github.com:TommyHilly/programFiles
* branch master -> FETCH_HEAD
git merge origin/master
Already up-to-date.
whenever new files are added or deleted, git pull
only works (git fetch/merge fails
).
$git pull
From github.com:TommyHilly/programFiles
b598c97..531d466 master -> origin/master
Updating b598c97..531d466
Fast-forward
README.txt | 2 ++
a.out | Bin 8496 -> 0 bytes
2 files changed, 2 insertions(+)
create mode 100644 README.txt
delete mode 100755 a.out
But when I have some files edited (nothing new added or deleted), git fetch
and merge
works fine.
Am I doing something wrong or is this how git
works?
EDIT:
git remote -v
origin git@github.com:TommyHilly/programFiles.git (fetch)
origin git@github.com:TommyHilly/programFiles.git (push)
EDIT 2:
Just doing git fetch
and git merge origin/master
seems to work. But I dont understand what is going on?
But git fetch origin master
followed by git merge origin/master
did not work?
回答1:
It's true that git pull
is really just git fetch
plus git merge
. But there are a bunch of caveats.
git fetch
When you run:
$ git fetch origin master
this "means":
$ git fetch origin master:FETCH_HEAD
which tells git fetch
to run over to origin
and ask them—github, in this case, and I will use "them" and "they" here to refer to origin
, so that "it" means "your fetch"—what they have for branch master
. Whatever they have, it brings over, but it puts that under the local special name FETCH_HEAD
.
If you run instead:
$ git fetch origin
this "means" for fetch
to run over to origin
and ask them about all their branches, and bring them all over as "remote branches". If they have branches "master" and "experiment", it brings those over as "remote branches" origin/master
and origin/experiment
.
git merge
First, git merge
always merges into your current branch (the one marked with a *
in git branch
output).1 In other words, it knows where to merge to. You need to tell it where to merge from, though.
If you run:
$ git merge
with no arguments, it has to figure out what commit-ID you want to "merge from". It does this by looking for a configuration variable, merge.defaultToUpstream
. If you get:
fatal: No commit specified and merge.defaultToUpstream not set.
this means merge.defaultToUpstream
is not set, or is set to false
instead of true
.
If you run git merge name-or-ID
, that tells git merge what to "merge from", so it does not need this special configuration variable. Hence:
$ git merge FETCH_HEAD
means "find the commit specified by FETCH_HEAD
". Or, if you run:
$ git merge origin/master
this means "find the commit specified by origin/master
".
Important: If you supply more than one extra argument to git merge
, it does an "octopus merge" (which I'm not going to describe in this answer). This means that git merge origin master
is quite different from git merge origin/master
. The slash makes a huge difference, because it changes the merge
command from a two-argument merge, to a one-argument merge. (I think it's unfortunate—and/or bad design—that git pull
has you use exactly those arguments, but they mean something quite different to git merge
.)
Putting them together
So, when do you want to supply FETCH_HEAD
to git merge
, and when do you want to supply origin/master
instead? Well, go back and re-read the section about git fetch above.
The FETCH_HEAD
method is the old2 way, in which you tell git fetch
both the place to fetch from, and the branch to fetch from, and have git fetch
write the result under the special name FETCH_HEAD
. It does not matter what branch you fetched: git fetch origin inigo_montoya
, git fetch origin you_killed_my_father
, git fetch origin inconceivable
: they all come over and get renamed FETCH_HEAD
, so that's what you merge with.
The origin/master
method is the new3 way: you run git fetch origin
and it just brings everything over and you can take your time and browse through "remote branches" at your leisure. Once you're happy with origin/master
and ready to merge it in, you merge it in by its (clear, simple, and obvious) name, instead of by FETCH_HEAD
.
git pull
Alas, git pull
.4 The pull
script still uses the "old way". When you run git pull origin master
, or even just git pull
with no arguments,5 it winds up running git fetch origin master
, which makes git fetch
behave the "old way". Then it uses git merge FETCH_HEAD
, which it has to, because it's just run git fetch
such that fetch did not update origin/master
.6
1Even if you're in the "detached HEAD" mode, git merge
still merges to your "current branch", sort of. It's just that the closest thing to "current branch" is now "the detached HEAD".
2Or maybe "traditional". I wish it were "obsolete", and that might happen eventually, but for now it's pretty deeply rooted.
3And far superior. :-)
4I don't like git pull
. It's meant as a convenience, and due to its insistence on doing things the "old way", it winds up being less convenient, not to mention one rare but serious bug it's had for a long time (fixed in git 1.8.4).
5With no arguments, git pull
gets the name of the remote and branch from the configuration for the current branch. If you're on branch master
, for instance, git reads branch.master.remote
and branch.master.merge
to get origin
and master
. These are the same values that make local branch master
a "tracking branch", tracking remote-branch origin/master
. Which is great, except git pull
forces git fetch
not to update origin/master
. So git pull
updates your local master
, but leaves things such that git tells you you're now ahead of origin/master
! Yuck. (This is fixed in git 1.8.4; git fetch
updates remote branches now, even while it writes to FETCH_HEAD
.)
6This is fixed in git 1.9, which might finally make git pull
a convenience method that's actually convenient. :-)
来源:https://stackoverflow.com/questions/21536126/will-fetch-merge-not-work-if-files-are-added-or-deleted-in-github-repository