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

use*_*506 101 git merge github

基本问题

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

git pull upstream master
Run Code Online (Sandbox Code Playgroud)

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

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

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

其他相关信息

我只有一个名为"master"的分支.

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

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

该命令git branch -vv产生:

* master 7cfcb29 [upstream/master: ahead 9] deletion test
Run Code Online (Sandbox Code Playgroud)

为什么会出现这种情况的原因?我只是通过电子邮件向我的项目经理发送任何我对代码所做的更改.

更新

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

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

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

tor*_*rek 189

我认为你的基本问题是你误解和/或误解了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
Run Code Online (Sandbox Code Playgroud)

这告诉git你想将当前目录移动到实际名称为的分支remotes/upstream/master.您将看到自上次运行git fetch并获取最新代码时的代码.

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

git checkout master
Run Code Online (Sandbox Code Playgroud)

那么git reset命令将允许你"移动标签",就像它一样.唯一剩下的问题(假设你真的准备放弃你所做的一切)就是找到标签所指的位置.

git log会让你找到数字名称 - 像7cfcb29永久(永不改变)名字这样的东西,还有一些荒谬的其他方法来命名它们,但在这种情况下你只需要这个名字upstream/master.

要移动标签,擦除你自己的更改(你提交的任何内容实际上都可以恢复很长一段时间,但是这之后要更加困难,所以要非常肯定):

git reset --hard upstream/master
Run Code Online (Sandbox Code Playgroud)

--hard告诉混帐消灭你一直在做什么,将当前分支标签,然后检查了指定的提交.

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

git branch -m master bunchofhacks
Run Code Online (Sandbox Code Playgroud)

然后创建一个名为master"track" 的新本地分支(我不喜欢这个术语,因为我觉得它让人困惑,但这就是git术语:-))起源(或上游)主人:

git branch -t master upstream/master
Run Code Online (Sandbox Code Playgroud)

然后你可以开始使用:

git checkout master
Run Code Online (Sandbox Code Playgroud)

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

在做任何事之前:

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "master"
Run Code Online (Sandbox Code Playgroud)

之后git branch -m:

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"
Run Code Online (Sandbox Code Playgroud)

之后git branch -t master upstream/master:

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

原因是HEAD^^从当前分支的头部(刚好在重置之前bunchofhacks)命名修订版本2 ,reset --hard然后移动标签.提交C8和C9现在几乎是不可见的(你可以使用像reflog这样的东西git fsck来找到它们,但它不再是微不足道的).无论你喜欢什么,你的标签都可以移动.该fetch命令负责处理开始的命令remotes/.将"你的"与"他们的"匹配是很常见的(所以如果他们也有remotes/origin/mauve你的名字mauve),但是只要你想要命名/看到"从他们那里得到"的提交,你就可以输入"他们的".(请记住,"一次提交"是一个完整的源代码树.您可以从一次提交中选择一个特定的文件,git show例如,如果需要,可以.)

  • 我从你的优秀答案中学到了很多东西.但我仍然感到困惑的是,为什么我得到git状态消息:"当你的上游仓库在我当前仓库之前的几次提交时,你的分支与'origin/master'是最新的".我可以通过git pull获取最新信息,但是如果消息显示我是最新的,我怎么知道我需要拉? (9认同)
  • `git pull` 首先运行 `git fetch`,然后运行 ​​`git merge` (或您选择的其他第二个命令)。“git fetch”步骤通过调用*他们的*Git 并从中获取任何新信息,更新*您的*Git 对*他们的*Git 状态的记忆。你的`git status`只检查你的Git对其Git的记忆。 (3认同)
  • @torek 除了 `git status` 之外,是否还有其他命令可以用来查看上游存储库是否在我当前的存储库之前?我用 `git status` 得到的消息说“你的分支是最新的,带有 'origin/master'”,这让我困惑地认为我已经得到了最新的更改,而我没有。有时,我确实收到一条消息,上面写着“origin/master is 5 commits before your branch”(释义)。但它并不一致。 (2认同)
  • 这实际上仍然没有回答为什么当立即的“git fetch”然后拉下一百多个对象并解析近一百个增量时,“git status”说“你的分支是最新的”,提到了几个新分支和几个新标签并更改主(远程跟踪)分支头提交 - 然后另一个 git 状态高兴地、不诚实地仍然说“你的分支是最新的”。显然有很多来自原点,但分支在之前和之后都“与原点保持同步”? (2认同)
  • 谢谢@torek,我在这里找到了一些清晰的信息:/sf/ask/2638616081/ means-without-chan 要实现的关键点是“远程跟踪分支”实际上是*本地*,并且*不*自动保持最新。因此,在“fetch”之前,“git status”只是与*本地*(远程)跟踪分支进行比较,该分支仍然很旧。`status` 不会与*实际*远程分支进行比较。“fetch”将更改从远程带到*本地*(远程)跟踪分支,然后“status”才有意义。 (2认同)

jtu*_*uri 8

我和你有同样的问题。

我做了git status git fetch git pull,但是我的分支仍然落后。我将文件夹和文件推送到远程,但我在网上看到了文件,但是在本地文件上却丢失了。

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

git fetch --all
git reset --hard origin/master 
Run Code Online (Sandbox Code Playgroud)

或者如果你想要一个分支

git checkout your_branch_name_here
git reset --hard origin/your_branch_name_here
Run Code Online (Sandbox Code Playgroud)

  • 它有效,但为什么会发生这种情况? (3认同)
  • 谢谢!这确实有效。请记住,分支名称区分大小写! (2认同)

Doc*_*ger 5

虽然这些答案都不适合我,但我可以使用以下命令解决该问题。

git fetch origin

这对我来说是一个伎俩。