'git pull origin mybranch'留下本地mybranch N提交原点之前提交。 为什么?

我只是观察到一些关于git pull东西,我不明白。

星期五,我在当地的一家分店工作。 让我们称之为mybranch 。 在离开办公室之前,我把它推到了原点(这是我的github回购): git push origin mybranch

昨天在家里,我pull我的笔记本电脑pull我的笔记本电脑上,做了一些更多的编码,然后把我的修改推回给github(原籍)。

现在我又在工作了,并且试图从昨天把改变拉到我的工作机器上(周末我在工作场所的本地回购中没有改变任何东西):

 git pull origin mybranch 

这导致了一个快速的前进合并,这很好。 然后我做了一个git status ,它说:

 # On branch mybranch # Your branch is ahead of 'origin/mybranch' by 6 commits. # nothing to commit (working directory clean) 

咦? 当我连周末都没有碰到它的时候,怎么可能会提前6分钟,刚从原点拉出来呢? 所以我运行了一个git diff origin/mybranch ,差异恰恰是我从远程获取的6个变化。

我只能通过运行git fetch origin “解决”这个问题:

 From git@github.com:me/project af8be00..88b0738 mybranch -> origin/mybranch 

显然,我的本地回购是缺less一些参考对象,但怎么可能呢? 我的意思是,拉已经提取了,除了那个分支我什么都没有做,所以一个git fetch origingit fetch origin mybranch应该有相同的结果?

我应该总是使用git pull origin而不是git pull origin branchname

我很困惑。

git pull在合并明确提取的头之前(或者如果没有configuration合并的远程分支)到当前分支之前,用合适的参数调用git fetch

语法: git fetch <repository> <ref>其中<ref>只是一个没有冒号的分支名称,是一次性提取,不会对指定远程的所有跟踪分支执行标准提取,而是取回只是命名分支到FETCH_HEAD

更新:对于自1.8.4以来的Git版本,如果有一个远程跟踪分支跟踪你要求提取的引用,那么跟踪分支现在将通过fetch进行更新。 这个改变是为了避免以前的行为造成的混乱。

当你执行git pull <repository> <ref>FETCH_HEAD被更新如上,然后被合并到你签出的HEAD但远程仓库的标准跟踪分支都不会被更新(Git <1.8.4)。 这意味着在本地它看起来像是在远程分支之前,而实际上你已经和它保持同步了。

就个人而言,我总是做git fetch后面跟着git merge <remote>/<branch>因为我在合并之前看到有关强制更新的任何警告,我可以预览我正在合并的东西。如果我用git pull了更多比我做的,我会做大部分时间没有参数的普通的git pull ,依靠branch.<branch>.remotebranch.<branch>.merge到'做正确的事情'。

git remote -v show什么时候返回来源?

如果origin指向github,状态应该是最新的,而不是任何远程repo。 至less,我用Git1.6.5进行了一个快速testing。

无论如何,为了避免这种情况,明确定义主分支的远程回购:

 $ git config branch.master.remote yourGitHubRepo.git 

那么一个git pull origin master ,随后一个git status应该返回一个干净的状态(不提前)。
为什么? 因为get fetch origin master(包含在git pull origin master中)不会更新FETCH_HEAD (正如Charles Bailey在他的答案中所解释的),但它也会更新本地Git存储库中的“remote master branch”。
在这种情况下,你的本地主人似乎不再是远在主人的“前面”了。


我可以用git1.6.5来testing这个:

首先我创build一个workrepo:

 PS D:\git\tests> cd pullahead PS D:\git\tests\pullahead> git init workrepo Initialized empty Git repository in D:/git/tests/pullahead/workrepo/.git/ PS D:\git\tests\pullahead> cd workrepo PS D:\git\tests\pullahead\workrepo> echo firstContent > afile.txt PS D:\git\tests\pullahead\workrepo> git add -A PS D:\git\tests\pullahead\workrepo> git commit -m "first commit" 

我通过创build一个裸回购(可以从任何地方接收推送)来模拟GitHub回购。

 PS D:\git\tests\pullahead\workrepo> cd .. PS D:\git\tests\pullahead> git clone --bare workrepo github 

我添加一个修改到我的工作回购,我推github回购(作为远程添加)

 PS D:\git\tests\pullahead> cd workrepo PS D:\git\tests\pullahead\workrepo> echo aModif >> afile.txt PS D:\git\tests\pullahead\workrepo> git ci -a -m "a modif to send to github" PS D:\git\tests\pullahead\workrepo> git remote add github d:/git/tests/pullahead/github PS D:\git\tests\pullahead\workrepo> git push github 

我创build了一个家庭回购,克隆了GitHub,我做了一些修改,推送到GitHub:

 PS D:\git\tests\pullahead\workrepo> cd .. PS D:\git\tests\pullahead> git clone github homerepo PS D:\git\tests\pullahead> cd homerepo PS D:\git\tests\pullahead\homerepo> type afile.txt firstContent aModif PS D:\git\tests\pullahead\homerepo> echo aHomeModif1 >> afile.txt PS D:\git\tests\pullahead\homerepo> git ci -a -m "a first home modif" PS D:\git\tests\pullahead\homerepo> echo aHomeModif2 >> afile.txt PS D:\git\tests\pullahead\homerepo> git ci -a -m "a second home modif" PS D:\git\tests\pullahead\homerepo> git push github 

然后我克隆workrepo第一个实验

 PS D:\git\tests\pullahead\workrepo4> cd .. PS D:\git\tests\pullahead> git clone workrepo workrepo2 Initialized empty Git repository in D:/git/tests/pullahead/workrepo2/.git/ PS D:\git\tests\pullahead> cd workrepo2 PS D:\git\tests\pullahead\workrepo2> git remote add github d:/git/tests/pullahead/github PS D:\git\tests\pullahead\workrepo2> git pull github master remote: Counting objects: 8, done. remote: Compressing objects: 100% (4/4), done. remote: Total 6 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (6/6), done. From d:/git/tests/pullahead/github * branch master -> FETCH_HEAD Updating c2763f2..75ad279 Fast forward afile.txt | Bin 46 -> 98 bytes 1 files changed, 0 insertions(+), 0 deletions(-) 

在这个回购中,git的地位确实提到了“ origin ”之前的主人。

 PS D:\git\tests\pullahead\workrepo5> git status # On branch master # Your branch is ahead of 'origin/master' by 2 commits. # nothing to commit (working directory clean) 

但是,这只是origin不是github:

 PS D:\git\tests\pullahead\workrepo2> git remote -v show github d:/git/tests/pullahead/github (fetch) github d:/git/tests/pullahead/github (push) origin D:/git/tests/pullahead/workrepo (fetch) origin D:/git/tests/pullahead/workrepo (push) 

但是如果我在一个有Github的起源的回购中重复序列(或者根本没有起源,只是一个远程的'github'定义),状态就是干净的:

 PS D:\git\tests\pullahead\workrepo2> cd .. PS D:\git\tests\pullahead> git clone workrepo workrepo4 PS D:\git\tests\pullahead> cd workrepo4 PS D:\git\tests\pullahead\workrepo4> git remote rm origin PS D:\git\tests\pullahead\workrepo4> git remote add github d:/git/tests/pullahead/github PS D:\git\tests\pullahead\workrepo4> git pull github master remote: Counting objects: 8, done. remote: Compressing objects: 100% (4/4), done. remote: Total 6 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (6/6), done. From d:/git/tests/pullahead/github * branch master -> FETCH_HEAD Updating c2763f2..75ad279 Fast forward afile.txt | Bin 46 -> 98 bytes 1 files changed, 0 insertions(+), 0 deletions(-) PS D:\git\tests\pullahead\workrepo4> git status # On branch master nothing to commit (working directory clean) 

如果我只有在github指向的origin ,git1.6.5的status将是干净的。
它可能与早期的git提前警告,但无论如何,显式定义的git config branch.master.remote yourGitHubRepo.git应该能够照顾,即使是早期版本的Git。

你是否小心使用git remote add NAME URL来添加所有的远程(除了原始克隆附带的origin )? 刚刚添加到gitconfiguration中时,我看到了这个bug。