Git本地分支不是最新的远程

Posted

技术标签:

【中文标题】Git本地分支不是最新的远程【英文标题】:Git local branch is not up to date with remote 【发布时间】:2022-01-05 23:02:27 【问题描述】:

我已经浏览了 4-5 个关于此的其他线程,但无法确定我哪里出错了。问题来了:

我有一个远程分支,in-progress-show-hide-countries

我登录了另一台尚未跟踪远程分支的 PC。 我运行了一些东西,可能是git pull,它获取了一些东西,但我的记忆在这里变得模糊。我注意到我的本地文件没有远程所做的更改。

以下是我尝试过的一些事情:

$ git status
On branch in-progress-show-hide-countries
Your branch is up to date with 'origin/in-progress-show-hide-countries'.

nothing to commit, working tree clean

git diff 没有显示代码差异,但更改在我的 github 上绝对可见。

$ git diff in-progress-show-hide-countries...origin/in-progress-show-hide-countries 

Git 日志显示我.. 可能??跟踪远程分支

$ git log
commit 4624760c5d66df430fc3d91fc718ffd04f27e292 (HEAD -> in-progress-show-hide-countries, origin/in-progress-show-hide-countries, main)

但也许我不知道我在说什么,所以这是我的 git remote -v

$ git remote -v
origin  git@github.com:XXX/fullstackopen.git (fetch)
origin  git@github.com:XXX/fullstackopen.git (push)

这个帖子 (How to compare a local Git branch with its remote branch) 建议我可以使用git diff <local branch> <remote>/<remote branch> 来查看我的本地分支和远程分支之间的区别,所以我尝试:

空输出

$ git diff in-progress-show-hide-countries origin/in-progress-show-hide-countries 

有什么线索吗?我意识到我可以在本地删除所有内容并重新克隆,但这对我的学习没有多大帮助。感谢任何建议。

【问题讨论】:

【参考方案1】:

您应该确保您在正确的分支上,您可以使用以下方法进行更改:

git checkout -b in-progress-show-hide-countries

如果您的系统没有真正的更改,则可以使用

git reset HEAD --hard

这将使您回到 Github 存储库上的最新提交。 不要轻易使用!被重置的作品无法恢复。

【讨论】:

执行此操作返回“HEAD 现在位于 4624760”。这是我要从中提取更改的远程提交的 SHA。但是,更改不会在本地显示。在这个命令之后,我尝试了 git fetch (没有响应)和 git status (在分支上进行中-显示-隐藏-国家你的分支是最新的'origin/in-progress-show-hide-countries'。) .我跳过了一步吗?【参考方案2】:

Git 的诀窍——嗯,好吧,其中一个诀窍——是认识到 分支 没有任何意义。您在 Git 中使用分支名称来跟踪 commits。重要的不是分支,而是提交。

那些 SHA ID,4624760c5d6...,才是最重要的。这些是 Git需要的。您可以将任意数量的名称​​附加到其中任何一个:

commit 4624760c5d66df430fc3d91fc718ffd04f27e292
(HEAD -> in-progress-show-hide-countries,
origin/in-progress-show-hide-countries, main)

这说明46247...有三个名字,分别是in-progress-show-hide-countriesorigin/origin/in-progress-show-hide-countriesmain。特殊名称 HEAD 是“附加到”名称 in-progress-show-hide-countries,这意味着 in-progress-show-hide-countries 是您当前的分支名称

使用分支名称可以避免每次都输入4624760c5d66df430fc3d91fc718ffd04f27e292。 (我每次都无法正确输入:我用鼠标进行剪切和粘贴。in-progress-show-hide-countries 有很多麻烦,我也剪切和粘贴。)除此之外,通过选择类似的名称mainin-progress-show-hide-countries 作为您的 当前 名称,您安排 Git 更新存储在 名称中的哈希 ID,每当您进行 新提交时间>。所以你的名字总是记得 latest 提交。一个漂亮、简短、易于输入、易于记忆的名称,例如 mainwip-shc 用于在 show-hide-countries 上进行的工作,是个好主意...适合您。 Git 不关心 名称; Git 关心 哈希 ID

提交自己为您记住提交哈希 ID。因此,每当您进行 new 提交时,新提交都会为您记住当时哪个提交是当前提交。进行 second 个新提交,新提交会记住 first 个新提交。

如果我们用一个简单的大写字母替换每个提交哈希 ID:

... <-F <-G <-H   <-- wip-shc (HEAD), main

我们可以看到将HEAD 附加到并进行新提交是如何工作的。记住提交总是像这样向后指向,我们创建一个新的提交I,其父级是当前提交H

... <-F <-G <-H   <-- main
               \
                I   <-- wip-shc (HEAD)

名称main 没有移动,但因为我们“在”分支wip-shc,名称wip-shc确实移动了。再次提交J,我们得到:

... <-F <-G <-H   <-- main
               \
                I <-J   <-- wip-shc (HEAD)

name 总是选择 last 提交,Git 从该提交向后工作。现在有两种方法可以提交 H,在这张图中(以及在现有存储库中提交的三种方法),但我们需要的是 some 方式,any 方式,到达那里以便找到它。 Git 会在需要时自动向后工作。您只需为其提供起始哈希 ID — 使用分支名称,如 wip-shcmain,或 远程跟踪名称,如 origin/in-progress-show-hide-countries

您的 Git 将自动创建或更新 远程跟踪名称——origin/in-progress-show-hide-countries 样式名称——当您的 Git 访问其存储库时,origin,1 并让他们列出他们的 分支名称。如果他们有in-progress-show-hide-countries 指向提交H,您的Git 将创建或更新您的origin/in-progress-show-hide-countries 以指向提交H

如果你的名字 wip-shc 指向 same 提交,因为他们的名字 in-progress-show-hide-countries 是你的 origin/in-progress-show-hide-countries,这两个名字是相互同步的,你是“最新的”。这就是全部的意思。


1令人困惑的是,Git 将 origin 称为 remote,而 origin/main 等因此是 远程跟踪分支名称。但是,一旦它们在您的存储库中,它们实际上并不是 branch 名称。所以我去掉了branch这个词,并称它们为remote-tracking names。更令人困惑的是,Git 至少以两种或三种不同的方式使用了 track 这个词。一个分支可以“跟踪”一个远程跟踪 [branch] 名称,文件要么是“跟踪”的,要么是“未跟踪的”,每一个都有不同的含义。


当你的文件不匹配时怎么办

您可以在任何存储库的任何克隆中查看和处理/使用的文件不在存储库中存储库中的文件以一种特殊的、只读的、仅 Git 的、压缩和去重的形式存储,只有 Git 可以读取,而实际上没有任何东西——甚至 Git 本身——也无法读取覆盖。这些文件对于完成任何新工作完全没有用处。所以这些文件不用于完成新工作。

相反,当您选择要处理的某个提交(通常使用 git checkoutgit switch)时,您是在指示 Git 从该提交中复制文件。这些文件从提交中出来并被解压缩回有用的形式(如果它们有重复,则会导致重复)。展开的文件进入您的工作树(有时缩短为工作树)。这些文件不是 in Git,即使它们来自 Git。

当您处理这些文件时,Git 内部不会发生任何事情。这些文件不在 Git 中,所以要更改它们——或者添加新文件,或者删除文件;你可以在这里做任何你想做的事——对 Git 没有影响

不过,在某些时候,您可能想使用这些更新的文件来进行新的提交。为此,您必须使用git add2 后跟git commit。这会产生新的提交,然后更新您当前的分支名称。

请注意,您的分支名称是您的。它们不在任何其他 Git 存储库中。如果您让某人克隆您的 Git 存储库,您的分支名称将成为其他人的远程跟踪名称(所以现在他们可以看到您的分支名称),但他们仍然是您的 分支 名称,不是别人的分支名称。其他人的分支名称可能是您的远程跟踪名称。

一旦你做了一个新的commit,你可能会也可能不会使用类似的分支名称,但现在它们不会同步。您通过向他们发送新的提交来进行同步,这就是 git push 的用武之地。


2您有时可以使用git commit -a 来避免git add 步骤。但是这样做以避免了解 Git 的索引是一个坏主意:Git 最终会用它的索引打你的头,迫使你去了解它。在发生紧急情况之前了解它。 Git 有时很痛苦,是的。


名称不必匹配

充分的理由在两个“边”上使用相同的名称,因为它是:试图记住变得非常疯狂,例如,my xyzzy 是 Fred 的插件,但是René 使用了 vue 这个名字,Sasha 称之为 супеp。如果每个人都使用相同的名称,那么您的origin/main 和您的main 至少具有相同的用途,即使哈希 ID 不同步。但在某些情况下,这实际上是不可能的:您可能有两个与您一起工作的人,他们都将他们的(不同的)分支称为 tall,因此有两个 remotes batmanrobin,你可以'不一定只有 一个 分支名称在您身边,称为 tall,所以您最终会得到 tall-batmantall-robin,或其他任何名称。

当您使用 git fetch 时,名称不必匹配,因为您的 Git 将创建或更新 远程跟踪名称。您将拥有origin/whatever 用于他们的分支whatever。你可以使用任何你喜欢的名字。

当您使用git push发送 提交 origin,但是,您必须在结束您的git push 时请求他们设置他们的分支名称。如果您有 匹配的分支名称,例如 batmanrobin 的情况,您可以这样做,例如:

git push robin robin-tall:tall

在这里,您在冒号: 的左侧写您的 分支名称,在右侧写他们的 分支名称。 (这里中间的 robinremote: 您发送提交的 URL 的简称;这与您使用 git fetch robin 的名称相同,这就是robin/tall 之类的名称来自:您的 Git 将远程名称粘贴到其分支名称的前面。3) 如果您的分支名称 do 匹配,则很简单:

git push origin somebranch

足够了:这意味着在双方都使用相同的名称,即,将我最新的somebranch 提交发送给他们,然后要求他们将这些提交合并到他们的中em> 名为somebranch 的分支。

他们可能拒绝更新他们的分支。在这种情况下,我们会遇到更复杂的情况:我们必须找出他们拒绝的原因,并弄清楚该怎么做。但到目前为止,这只是git push 的简单部分。这意味着向他们发送他们尚未提交的我的新提交,然后要求他们设置他们的分支名称之一。您必须选择要发送的提交(即从冒号的左侧)和名称,从右侧。如果您在两边使用相同的名称,则可以省略冒号并输入less。


3内部实际上要复杂得多——毕竟这是 Git 的传统,没有什么可以像看起来那么简单——但这就是最终效果。

【讨论】:

非常感谢您的详尽解释。这将需要我一些时间来消化,但它非常有启发性。如果我没记错的话,这里的外卖信息是“你的分支是最新的'origin/in-progress-show-hide-countries'”。并不意味着我的本地更改反映了最新的提交:重要的是我正在处理与远程提交哈希相同的提交(这确保我正在处理我想要处理的代码库,假设 HEAD也指向该特定哈希)。听上去是不是觉得我理解的更透彻了? 是的 - 您可能有不同的签出文件,但您从相同的起点开始,即相同的提交哈希 ID。

以上是关于Git本地分支不是最新的远程的主要内容,如果未能解决你的问题,请参考以下文章

Git使用手册/Git教程:git fetch 将远程仓库的分支及分支最新版本代码拉取到本地

Git 拉取远程代码

Git关于远程分支--我的理解:远程分支永远是存储最新的版本。

为啥“合并后删除分支”只删除远程GIT分支而不是本地?

本地 GIT 分支和远程 GITHUB 分支是不是需要相同才能推送代码? [复制]

git 抓取远程分支到本地分支(本地不存在这个分支)