【问题标题】:'git pull origin mybranch' leaves local mybranch N commits ahead of origin. Why?'git pull origin mybranch' 在 origin 之前离开本地 mybranch N 提交。为什么?
【发布时间】:2010-12-17 00:03:57
【问题描述】:

我刚刚观察到 git pull 的一些奇怪之处,我不明白。

周五,我在当地的一家分公司工作。我们称之为mybranch。在离开办公室之前,我将其推送到 origin(这是我的 github 仓库):git push origin mybranch

昨天在家里,我 pulled mybranch 到我的笔记本电脑,进行了一些编码,然后将我的更改推送回 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

显然,我的本地仓库缺少一些参考对象,但这怎么可能呢?我的意思是,pull 已经进行了 fetch,除了那个分支我什么都没做,所以 git fetch origingit fetch origin mybranch 应该有相同的结果?

我是否应该始终使用git pull origin 而不是git pull origin branchname

我很困惑。

【问题讨论】:

  • 我也注意到了这一点; git push 似乎也可以解决它(报告“所有最新”)。
  • git config --get-regexp br.* 可以告诉您您的配置是否有一个本地分支正在跟踪另一个分支
  • 您能否在您的 workRepo 中输入 git config branch.master.remote yourGitHubRepo.git 并检查(在下一个 git pull origin)状态是否仍然带有“提前”警告?
  • 未设置(空输出)。但是git remote show origin 告诉我 origin 指向我的 GitHub 存储库,所以我猜应该没问题?
  • 仅 git remote(显示 GitHub repo 的正确地址)还不够。为避免在git pull 之后出现“Your branch is ahead”警告消息,您首先需要 定义分支的远程名称。因此我的建议是:输入git config branch.master.remote yourGitHubRepo.git,然后尝试git pullgit status,看看问题是否仍然存在。

标签: git version-control git-pull


【解决方案1】:

git pull 使用适当的参数调用git fetch,然后将显式获取的头(或者如果没有配置为合并的远程分支)合并到当前分支。

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

更新:对于自 1.8.4 以来的 Git 版本,如果有一个远程跟踪分支可以跟踪您要求获取的 ref,那么该跟踪分支现在将由 fetch 更新。进行此更改是为了避免之前的行为造成的混乱。

当您执行git pull <repository> <ref> 时,FETCH_HEAD 会按上述方式更新,然后合并到您签出的HEAD,但不会更新远程存储库的标准跟踪分支(Git 看起来就像你领先于远程分支,而实际上你是最新的。

就我个人而言,我总是先使用git fetch,然后使用git merge <remote>/<branch>,因为我会在合并之前看到任何有关强制更新的警告,并且我可以预览我正在合并的内容。如果我使用git pull 多一点我愿意,我会做一个普通的git pull,大部分时间没有参数,依靠branch.<branch>.remotebranch.<branch>.merge 来“做正确的事”。

【讨论】:

  • +1 这真是一个很好的解释!我知道解释隐藏在 'git help fetch' 中的某个地方,但无法将它弄出来......
  • +1。好帖子,方法类似于gitster.livejournal.com/28309.html
  • 那么git fetchgit pull <repository> <ref> 之后会解决问题,因为提取会更新标准跟踪分支吗?另外,感谢这个答案,开始有意义:)
  • 我也遇到了这个问题,你需要先git fetch,然后是git merge origin/master master
【解决方案2】:

git remote -v show 在原点返回什么?

如果 origin 指向 github,则状态应该是最新的,而不是在任何远程 repo 之前。至少,我使用 Git1.6.5 进行快速测试。

无论如何,为避免这种情况,明确定义 master 分支的远程 repo:

$ git config branch.master.remote yourGitHubRepo.git

然后一个git pull origin master,后跟一个git status应该返回一个干净的状态(没有提前)。
为什么?因为 get fetch origin master(包含在 git pull origin master 中)不仅会更新FETCH_HEAD(正如Charles Baileyhis answer 中解释的那样),但它会更新“远程主本地 Git 存储库中的“分支”。
在这种情况下,您的本地主机似乎不再“领先”于远程主机。


我可以用 git1.6.5 测试一下:

首先我创建一个工作仓库:

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"

我通过创建一个裸仓库(可以从任何地方接收推送)来模拟 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

我创建了一个从 GitHub 克隆的 home repo,我在其中做了一些修改,然后推送到了 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(-)

在那个 repo 中,git status 确实提到了 master 领先于 '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)

如果我只有 origin 指向 githubstatus 对于 git1.6.5 将是干净的。
对于早期的 git,它可能带有“提前”警告,但无论如何,明确定义的 git config branch.master.remote yourGitHubRepo.git 应该能够解决这个问题,即使是早期版本的 Git。

【讨论】:

  • 感谢您抽出宝贵时间调查此事。源远程已经指向我的 GitHub 存储库。我从 GitHub url 克隆了该项目,我的本地 master 分支正在跟踪 origin/master。至于 mybranch,我很确定我是从 origin/mybranch 分支创建的,它应该会自动跟踪它。但是,也许这就是问题所在?本地 mybranch 实际上并不跟踪 origin/mybranch? PS:我正在使用 git 1.6.1(通过 MacPorts)。
  • 是否有 git 命令可以让我查看本地分支是否正在跟踪另一个分支?我在手册页中找不到它。
  • 您可以通过git remote show origin查看哪些远程分支被跟踪。
【解决方案3】:

您是否小心使用git remote add NAME URL 添加所有遥控器(除了原始克隆附带的origin)?当它们刚刚被添加到 git 配置中时,我已经看到了这个错误。

【讨论】:

  • 我在克隆 repo 时这样做了。但是,我没有对每个分支都这样做。例如mybranch 我会先从原点获取,然后是git checkout -b mybranch origin/mybranch。根据 git-branch 的手册页, origin/mybranch 是起点,此外,它指出 --track :“......如果你总是从同一个上游分支拉到新分支,请使用这个,并且如果您不想显式使用“git pull ”。当起点是远程分支时,此行为是默认行为。“
猜你喜欢
  • 2017-03-09
  • 1970-01-01
  • 2017-04-15
  • 2021-08-03
  • 2021-02-05
  • 2011-11-13
  • 2015-10-06
  • 2011-02-22
相关资源
最近更新 更多