为什么Git说我的主分支“已经是最新的”,即使它不是?

基本问题

我刚刚从我的项目中的一个文件中删除了所有代码,并将更改提交给本地git(故意使用)。 我做了

git pull upstream master 

从上游获取和合并(理论上说,删除的代码应该回来)。

Git告诉我一切都是最新的。

一切都是最新的 – 所有删除的代码仍然被删除。

其他相关信息

我只有一个分支叫“主人”。

我最近成立了“大师”来追踪上游如下:

分支主机设置为从上游跟踪远程分支主机。

命令git branch -vv产生:

 * master 7cfcb29 [upstream/master: ahead 9] deletion test 

为什么为什么会这样呢? 我正在向我的项目经理发送电子邮件,以便对我们的代码进行任何更改。

更新

我认为这很明显,但无论如何这是我的目标:

获取我的系统上最新的代码。

请原谅我的愤怒,但为什么这么简单的工作要这么辛苦呢?

我认为你的基本问题在于你误解和/或误解了git做了什么以及为什么这么做。

当你克隆一些其他仓库时,git会制作一个“在那边”的副本。 它也需要“他们的”分支标签,如master ,并在你的混帐树的“全名”(通常) remotes/origin/master (但在你的情况下, remotes/upstream/master ) 。 大多数情况下,您也可以省略remotes/部件,因此您可以将原始副本称为upstream/master

如果您现在对某些文件进行了一些更改,那么您是唯一有这些更改的文件。 与此同时,其他人可能会使用原始存储库(从中创build您的克隆)来制作其他克隆并更改这些克隆。 当然,他们是唯一有变化的人。 最终,有人可能会有变化,他们发回原始的所有者(通过“推”或补丁或其他)。

git pull命令通常只是git fetch缩写,然后是git merge 。 这很重要,因为这意味着你需要了解这两个操作实际上做了什么。

git fetch命令说回到你克隆的任何地方(或者有其他设置作为获取的地方),并find“新的东西,别人添加或更改或删除”。 这些更改将被复制并应用于您之前从他们那里获得的副本 。 他们不适用于你自己的工作,只适用于他们的工作。

git merge命令比较复杂,是你要去的地方。 它做了什么,过于简单化了一下,比较了“你在副本中改变了什么”,“改变了你从别人那里获得的改变,因此被添加到了你的副本”。 如果你的改变和它们的改变似乎没有冲突,那么merge操作将它们merge在一起,并给你一个“合并提交”,将你的发展和他们的发展联系在一起(虽然有一个非常普遍的“简单”没有变化,你得到一个“快进”)。

你现在遇到的情况是,你已经做了九次改变和承诺,实际上是“前进九号” – 他们没有任何改变。 所以,尽职尽责地提取任何东西,然后merge采取他们的缺乏变化,也什么都不做。

你想要的是看,甚至“重置”,“他们”的代码版本。

如果你只是想看看它,你可以简单地看看这个版本:

 git checkout upstream/master 

这就告诉git你要把当前目录移到全名是remotes/upstream/master的分支remotes/upstream/master 。 你会看到他们的代码,你上次运行git fetch并获得他们最新的代码。

如果你想放弃所有你自己的改变,你需要做的是改变你的标签, master应该命名哪个版本的git的想法。 目前它命名你最近的提交。 如果你回到那个分支:

 git checkout master 

那么git reset命令将允许您“移动标签”,就像它一样。 唯一剩下的问题(假设你真的准备放弃你所做的一切)是find标签应该指向的地方。

git log会让你find数字名称,比如7cfcb29 ,它们是永久的(永远不会改变)名字,而且有很多其他的方法来命名它们,但是在这种情况下,你只需要命名为upstream/master

要移动标签,清除你自己的变化(任何你已经提交的实际上可以恢复的时间,但这是非常困难之后,所以很难确定):

 git reset --hard upstream/master 

--hard告诉git清除你一直在做的事情,移动当前的分支标签,然后检查给出的提交。

真的想要git reset --hard并不是非常常见的 – git reset --hard并且消除了一堆工作。 一个更安全的方法(如果你决定完成一些工作比较容易,恢复这个工作就容易多了)是重命名你现有的分支:

 git branch -m master bunchofhacks 

然后创build一个新的本地分支名为“追踪”的master (我不太喜欢这个词,因为我认为它使人混淆,但这就是git术语:-))起源(或上游)主人:

 git branch -t master upstream/master 

然后你可以使用下面的方法:

 git checkout master 

最后三个命令做什么(有两个命令的快捷方式)是更改粘贴在现有标签上的名称,然后创build一个新标签,然后切换到它:

在做任何事之前:

 C0 - "remotes/upstream/master" \ \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "master" 

git branch -m

 C0 - "remotes/upstream/master" \ \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks" 

git branch -t master upstream/master

 C0 - "remotes/upstream/master", "master" \ \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks" 

这里的C0是你第一次做git clone时得到的最新提交(一个完整的源代码树)。 C1到C9是你的提交。

请注意,如果你要git checkout bunchofhacks ,然后git reset --hard HEAD^^ ,这将改变最后的图片:

 C0 - "remotes/upstream/master", "master" \ \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 - "bunchofhacks" \ \- C8 --- C9 

原因在于HEAD^^从当前分支的头部(在复位之前将会是bunchofhacks )命名修订版本2,然后reset --hard然后移动标签。 提交C8和C9现在大部分是不可见的(你可以使用像reflog和git fsck来find它们,但不再微不足道)。 不pipe你喜欢,你的标签都是你的标签。 fetch命令照顾那些以remotes/开头的命令。 将“你的”与“他们的”相匹配是常规的(所以如果他们有一个remotes/origin/mauve ,你也可以mauve ),但是只要你想命名/看到你提交的提交,就可以input他们的“从他们”。 (请记住,“一个提交”是一个完整的源代码树,你可以从一个提交中挑选出一个特定的文件,例如git show ,如果你想要的话。

正如其他海报所说的,将上游的更改合并到您的存储库中。 如果您想要将存储库中的内容replace为上游中的内容,则有多个选项。 袖口,我会去

 git checkout HEAD^1 # Get off your repo's master.. doesn't matter where you go, so just go back one commit git branch -d master # Delete your repo's master branch git checkout -t upstream/master # Check out upstream's master into a local tracking branch of the same name 

您提交的任何更改(如删除所有项目文件)在拉出后仍将保留。 所有的pull都会将其他地方的最新变化合并到你自己的分支中,如果你的分支已经删除了所有的东西,那么当上游变化影响你删除的文件的时候,你最好会得到合并冲突。 所以,总之,是的,一切都是最新的。

如果您描述了您希望得到的结果,而不是“删除所有文件”,也许有人可以build议适当的行动。

更新:

在我的系统上获取最新的代码

你似乎不明白的是,你已经有最近的代码,这是你的。 如果您真正想要查看其他人在Master分支上工作,请执行以下操作:

 git fetch upstream git checkout upstream/master 

请注意,这不会让你立即(重新)开始自己的工作。 如果您需要知道如何撤消您已完成的操作,或者恢复您或其他人所做的更改,请提供详细信息。 另外,考虑阅读什么是版本控制,因为你似乎误解了它的基本目的。

有人请纠正我,如果我错了,但我相信这是因为你的分支比上游主分支提前9次提交。 当你从遥控器拉出来的时候,你已经有了这些改变,只是你提前9次提交。 对于那些已经在你的历史中已经有了9次提交的旧的改变,将无法取代你的新改变。

我相信如果远程提交更新, 那么它们将被合并(默认情况下,除非指定--rebase )到您当前的分支。

就像Ryan说的那样,我build议你明确指出你的目标是什么,以便有人可以更直接地帮助你。

从给定的信息的广度和深度来看,最好的答案要好得多,但是似乎如果你想立即修复你的问题,不要介意一些版本控制的基本原理,你可以…

  1. 切换到主

     $ git checkout upstream master 
  2. 删除不需要的分支。 (注意:它必须具有-D,而不是正常的-d标志,因为你的分支在主机之前有很多提交。)

     $ git branch -d <branch_name> 
  3. 创build一个新的分支

     $ git checkout -b <new_branch_name>