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

时间:2013-03-13 02:58:31

标签: git github merge

基本问题

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

git pull upstream master

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

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

一切都绝对不是最新的 - 所有删除的代码仍然被删除。

其他相关信息

我只有一个名为“master”的分支。

我最近设置了“master”来跟踪上游,如下所示:

  

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

命令git branch -vv产生:

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

为什么会出现这种情况的原因?我正在向我的项目经理发送电子邮件,以便对我们的代码进行任何更改。

更新

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

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

请原谅我的愤怒,但为什么这么简单的任务必须如此努力呢?

8 个答案:

答案 0 :(得分:176)

我认为你的基本问题是你误解和/或误解了git的作用及其原因。

当你克隆一些其他的存储库时,git会复制那些"那边的#34;。它还需要"他们的"分支标签,例如master,并制作该标签的副本,其全名为"在你的 git树中是(通常)remotes/origin/master(但在你的情况下,remotes/upstream/master)。大多数情况下,您也会忽略remotes/部分,因此您可以将该原始副本称为upstream/master

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

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

git fetch命令说回到你克隆的任何地方(或以其他方式设置为取得的地方)并找到其他人添加或更改或删除的新内容。 。这些更改将复制并应用于到您之前从中获取的内容的副本。它们适用于您自己的作品,仅适用于他们的作品。

git merge命令更复杂,是你出错的地方。它做了什么,过度简化了一下,比较了你在副本中改变了什么"改变你从别人那里获得的改变,从而被添加到你的另一个人的副作品中#s;#34;。如果您的更改和他们的更改似乎没有冲突,merge操作会将它们组合在一起并为您提供"合并提交"这将你的发展与他们的发展联系在一起(虽然有一个非常普遍的#34;轻松"你没有变化的情况,你会得到一个快进#34;)。

您现在遇到的情况是您已经进行了更改并提交了它们的情况 - 实际上是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

要移动标签,消除您自己的更改(您提交的任何内容实际上可以恢复很长一段时间,但在此之后它会变得更加困难,因此非常确定):< / p>

git reset --hard upstream/master

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

真的想要git reset --hard并消除大量工作并非超常见。一个更安全的方法(如果你决定其中一些是值得的,那么恢复这项工作要容易得多)就是重命名你现有的分支:

git branch -m master bunchofhacks

然后创建一个名为master的新本地分支,&#34;跟踪&#34; (我不喜欢这个术语,因为我觉得它让人困惑,但这就是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^^将修订版本2命名为当前分支的头部(在重置之前为bunchofhacks),然后reset --hard移动标签。提交C8和C9现在几乎是不可见的(您可以使用reflog和git fsck之类的东西来查找它们,但它不再是微不足道的)。无论你喜欢什么,你的标签都可以移动。 fetch命令负责处理以remotes/开头的命令。匹配&#34;你的&#34;是常规的。用他们的&#34;他们的&#34; (如果他们有一个remotes/origin/mauve,你也可以为你mauve命名),但你可以输入&#34;他们的&#34;无论何时你想要命名/看到你得到的提交&#34;来自他们&#34;。 (请记住,&#34;一次提交&#34;是一个完整的源代码树。例如,如果需要,可以从一次提交中选择一个特定文件,例如git show。)

答案 1 :(得分:4)

我和你有同样的问题。

我做了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

答案 2 :(得分:3)

正如其他海报所说,拉动将上游的变化合并到您的存储库中。如果要将存储库中的内容替换为上游内容,则可以使用多个选项。脱下袖口,我会去

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

答案 3 :(得分:2)

您提交的任何更改(例如删除所有项目文件)在拉动后仍会保留。所有的拉动都是将来自其他地方的最新更改合并到您自己的分支中,如果您的分支已经删除了所有内容,那么当上游更改影响您删除的文件时,最多会出现合并冲突。所以,简而言之,是的,一切都是最新的。

如果你描述了你想要的结果而不是“删除所有文件”,那么也许有人可以提出适当的行动方案。

<强>更新

  

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

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

git fetch upstream
git checkout upstream/master

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

答案 4 :(得分:1)

如果我错了,请有人纠正我,但我相信这是因为你的分支在9次提交之前领先于上游主分支。当您从遥控器进行拉动时,您已经进行了这些更改,只需要通过9次提交就可以领先它们。对于那些您已经在历史中已经拥有并且提前9次提交的旧更改来替换您的新更改是没有意义的。

我相信如果遥控器中的提交更新然后,它们将被合并(默认情况下;除非您指定--rebase)到当前分支。

像Ryan所说,我建议你准确说明你的目标是什么,以便有人可以更直接地帮助你。

答案 5 :(得分:1)

在给出的信息的广度和深度方面,最佳答案要好得多,但似乎您希望几乎立即修复问题,并且不介意对版本控制的一些基本原则进行研究,您可以...

  1. 切换到主

    <missing>
  2. 删除不需要的分支。 (注意:它必须是-D,而不是普通的-d标志,因为你的分支在主服务器之前有很多提交。)

    $ git checkout upstream master
    
  3. 创建新分支

    $ git branch -d <branch_name>
    

答案 6 :(得分:0)

虽然这些答案对我都不起作用,但我可以使用以下命令解决此问题。

git fetch origin

这对我来说是个把戏。

答案 7 :(得分:0)

如果您有本地不在github中的文件,但是您的git status说,

您的分支机构的最新信息是“来源/主”。 没什么要提交的,正在工作的树很干净

如果文件位于.gitignore

中,则可能会发生

尝试运行

cat .gitignore 

,然后查看这些文件是否在那里显示。那可以解释为什么git不想将它们移动到远程。