为什么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议你明确指出你的目标是什么,以便有人可以更直接地帮助你。
从给定的信息的广度和深度来看,最好的答案要好得多,但是似乎如果你想立即修复你的问题,不要介意一些版本控制的基本原理,你可以…
-
切换到主
$ git checkout upstream master
-
删除不需要的分支。 (注意:它必须具有-D,而不是正常的-d标志,因为你的分支在主机之前有很多提交。)
$ git branch -d <branch_name>
-
创build一个新的分支
$ git checkout -b <new_branch_name>