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

基本问题

我只是删除了所有的代码,从我的项目中的一个文件,并提交了我的本地 git 的变化(目的)。是的

git pull upstream master

从上游获取和合并(因此理论上删除的代码应该返回)。

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

所有的东西肯定不是最新的——所有被删除的代码仍然被删除。

其他相关资料

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

我最近创建了“ master”来跟踪上游,就像这样:

设立分公司主管,从上游跟踪远程分公司主管。

命令 git branch -vv产生:

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

为什么会这样?我马上就要给我的项目经理发邮件告诉他我对代码做了什么修改。

更新

我认为这是显而易见的,但无论如何,这是我的目标:

在我的系统里找到最新的代码。

请原谅我的愤怒,但是为什么这么简单的任务就这么难呢?

274862 次浏览

您所提交的任何更改,比如删除所有项目文件,在一次提取之后仍将保持不变。一次拉取操作所做的就是将最新的来自其他地方的更改合并到您自己的分支中,如果您的分支已经删除了所有内容,那么当上游更改影响您已删除的文件时,您最多只会得到合并冲突。所以,简而言之,是的,一切都是最新的。

如果你描述的是你想要的结果,而不是“所有的文件删除”,也许有人可以建议一个适当的行动过程。

更新:

找到我系统里最新的代码

您似乎不明白的是,您已经拥有了最新的代码,也就是您的代码。如果你真的想看到主分支上最新的 别人的作品,只需要:

git fetch upstream
git checkout upstream/master

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

正如其他发布者所说,将上游的更改合并到您的存储库中。如果您想用上游存储库中的内容替换存储库中的内容,那么有几种选择。即兴发挥,我也会这么想

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

我认为你在这里的基本问题是,你正在误解和/或误解什么 git 做,为什么它这样做。

当您克隆一些其他存储库时,git 会复制“那里”的内容。它还获取“ their”分支标签,例如 master,并复制 你的 git 树中“全名”为(通常) remotes/origin/master的标签(但在您的例子中是 remotes/upstream/master)。大多数情况下,您也可以省略 remotes/部分,所以您可以将原始副本称为 upstream/master

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

git pull命令基本上只是 git fetch后跟 git merge的简写。这一点很重要,因为这意味着您需要了解这两个操作实际上是做什么的。

git fetch命令要求返回到您从哪里克隆(或者以其他方式设置为从哪里提取)的位置,并找到“其他人添加、更改或删除的新内容”。这些更改将被复制并应用于 你之前从他们那里拿到的复印件。他们是 没有应用到你自己的工作,只有他们的。

git merge命令更加复杂,这正是出错的地方。它所做的,有点过于简单化了,就是将“你在你的拷贝中修改的内容”与“你从别人那里获取的修改内容,并因此被添加到你的别人的拷贝中”进行比较。如果您的更改和它们的更改似乎没有冲突,那么 merge操作将它们混合在一起,并提供一个“合并提交”,将您的开发和它们的开发绑定在一起(尽管有一个非常常见的“简单”情况,即您没有更改,但您得到了一个“快进”)。

您现在遇到的情况是您已经进行了更改并提交了更改ーー实际上是9次,因此是“提前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 术语: ——)原始(或上游)主机:

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/开头的命令。常规的做法是将“你的”和“他们的”匹配起来(所以如果他们有一个 remotes/origin/mauve,你也可以将你的命名为 mauve) ,但是你可以在任何时候输入“他们的”来命名/查看你从他们那里得到的提交。(请记住,“一次提交”是一个完整的源代码树。您可以从一次提交中选择一个特定的文件,例如,如果需要的话,可以使用 git show。)

从所给信息的广度和深度来看,最好的答案要好得多,但是如果您希望几乎立即解决问题,并且不介意尝试一些版本控制的基本原则,那么您可以..。

  1. 切换到主机

    $ git checkout upstream master
    
  2. Delete your unwanted branch. (Note: it must be have the -D, instead of the normal -d flag because your branch is many commits ahead of the master.)

    $ git branch -d <branch_name>
    
  3. Create a new branch

    $ git checkout -b <new_branch_name>
    

我和你有同样的问题。

我做了 git status git fetch git pull,但我的分支仍然落后于原点。我有文件夹和文件推到远程,我在网上看到的文件,但在我的本地失踪。

最后,这些命令更新了本地的所有文件和文件夹:

git fetch --all
git reset --hard origin/master

或者你想要一根树枝

git checkout your_branch_name_here
git reset --hard origin/your_branch_name_here

虽然这些答案都不适合我,但是我能够使用以下命令修复这个问题。

git fetch origin

这对我有好处。

只是一个友好的提醒,如果你有文件在本地不在 github,但你的 git status

你的分行已更新为「原产地/主人」。 没什么可承诺的,干净利落地工作

如果文件在 .gitignore中,就会发生这种情况

试着逃跑

cat .gitignore

看看这些文件能不能在那里找到。这就解释了为什么 Git 不想把它们移到遥控器上。