我认为你的基本问题是你误解和/或误解了 git 的作用以及它为什么这样做。
当您克隆其他存储库时,git 会复制“那里”的任何内容。它还采用“他们的”分支标签,例如master,并制作该标签的副本,该标签在你的 git树中的“全名”(通常)是remotes/origin/master(但在你的情况下) ,remotes/upstream/master)。大多数情况下,您也可以省略remotes/ 部分,因此您可以将原始副本称为upstream/master。
如果您现在对某些文件进行并提交一些更改,那么您是唯一拥有这些更改的人。同时,其他人可能会使用原始存储库(您从中进行克隆)来创建其他克隆并更改这些克隆。当然,他们是唯一发生变化的人。但最终,有人可能会将更改发回给原始所有者(通过“推送”或补丁或其他方式)。
git pull 命令主要是git fetch 后跟git merge 的简写。这很重要,因为这意味着您需要了解这两个操作的实际作用。
git fetch 命令说返回到您克隆的位置(或以其他方式设置为从中获取的位置)并找到“其他人添加、更改或删除的新内容”。这些更改会被复制并应用到您之前从它们那里获得的内容的副本中。它们不应用于您自己的工作,仅应用于他们的工作。
git merge 命令更复杂,是你要出错的地方。它的作用,有点过于简单化了,是将“你在副本中更改的内容”与“您从其他人那里获取的更改并因此添加到您的其他人的工作副本中”进行比较。如果您的更改和他们的更改似乎没有冲突,merge 操作会将它们混合在一起,并为您提供一个“合并提交”,将您的开发和他们的开发联系在一起(尽管有一个非常常见的“简单”案例,其中你没有任何变化,你得到一个“快进”)。
您现在遇到的情况是您进行了更改并提交了它们——实际上是九次,因此是“提前 9 次”——并且他们没有进行 更改。所以,fetch 尽职尽责地什么也不做,然后merge 接受他们缺少的变化,也不做任何事情。
您想要的是查看,或者甚至“重置”到“他们的”代码版本。
如果你只是想看它,你可以简单地查看那个版本:
git checkout upstream/master
这告诉 git 你想将当前目录移动到全名实际上是remotes/upstream/master 的分支。您将看到他们上次运行 git fetch 并获得他们最新代码时的代码。
如果您想放弃您自己的所有更改,您需要做的是更改 git 的想法,即您的标签 master 应该命名哪个修订版本。目前它命名你最近的提交。如果你回到那个分支:
git checkout master
然后git reset 命令将允许您“移动标签”,就像它一样。剩下的唯一问题(假设你真的准备好放弃你所做的一切)是找到标签应该指向的位置。
git log 会让你找到数字名称——像7cfcb29 这样的东西——它们是永久的(永远不会改变的)名称,还有很多其他的方法来命名它们,但在这种情况下你只想要名字upstream/master。
要移动标签,清除您自己的更改(您已提交的任何更改实际上都可以在很长一段时间内恢复,但在此之后会变得更加困难,所以非常确定):
git reset --hard upstream/master
--hard 告诉 git 清除你一直在做的事情,移动当前分支标签,然后检查给定的提交。
真的想要git reset --hard 并消除一堆工作并不常见。一种更安全的方法(如果您认为其中一些工作是值得的,则更容易恢复该工作)是重命名您现有的分支:
git branch -m master bunchofhacks
然后创建一个名为 master 的新本地分支,用于“跟踪”(我不太喜欢这个术语,因为我认为它会使人感到困惑,但这是 git 术语 :-))起源(或上游)master:
git branch -t master upstream/master
然后你就可以自己动手了:
git checkout master
最后三个命令的作用(有快捷方式可以使它成为两个命令)是更改粘贴在现有标签上的名称,然后创建一个新标签,然后切换到它:
在做任何事情之前:
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),然后reset --hard 移动标签。提交 C8 和 C9 现在大部分是不可见的(您可以使用 reflog 和 git fsck 之类的东西来找到它们,但这不再是微不足道的)。您的标签可以随心所欲地移动。 fetch 命令处理以remotes/ 开头的命令。将“yours”与“theirs”匹配是常规的(所以如果他们有remotes/origin/mauve,你也可以将你的命名为mauve),但你可以在想要命名/查看提交时输入“theirs”“从他们”。 (请记住,“一次提交”是一整棵源代码树。您可以从一次提交中挑选出一个特定文件,例如,如果需要,可以使用 git show。)