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-countries
、origin/origin/in-progress-show-hide-countries
和main
。特殊名称 HEAD
是“附加到”名称 in-progress-show-hide-countries
,这意味着 in-progress-show-hide-countries
是您当前的分支名称。
使用分支名称可以避免每次都输入4624760c5d66df430fc3d91fc718ffd04f27e292
。 (我每次都无法正确输入:我用鼠标进行剪切和粘贴。in-progress-show-hide-countries
有很多麻烦,我也剪切和粘贴。)除此之外,通过选择类似的名称main
或 in-progress-show-hide-countries
作为您的 当前 名称,您安排 Git 更新存储在 名称中的哈希 ID,每当您进行 新提交时间>。所以你的名字总是记得 latest 提交。一个漂亮、简短、易于输入、易于记忆的名称,例如 main
或 wip-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-shc
或 main
,或 远程跟踪名称,如 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 checkout
或 git switch
)时,您是在指示 Git 从该提交中复制文件。这些文件从提交中出来并被解压缩回有用的形式(如果它们有重复,则会导致重复)。展开的文件进入您的工作树(有时缩短为工作树)。这些文件不是 in Git,即使它们来自 Git。
当您处理这些文件时,Git 内部不会发生任何事情。这些文件不在 Git 中,所以要更改它们——或者添加新文件,或者删除文件;你可以在这里做任何你想做的事——对 Git 没有影响。
不过,在某些时候,您可能想使用这些更新的文件来进行新的提交。为此,您必须使用git add
2 后跟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 batman
和 robin
,你可以'不一定只有 一个 分支名称在您身边,称为 tall
,所以您最终会得到 tall-batman
和 tall-robin
,或其他任何名称。
当您使用 git fetch
时,名称不必匹配,因为您的 Git 将创建或更新 远程跟踪名称。您将拥有origin/whatever
用于他们的分支whatever
。你可以使用任何你喜欢的名字。
当您使用git push
来发送 提交到 origin
,但是,您必须在结束您的git push
时请求他们设置他们的分支名称。如果您有 不 匹配的分支名称,例如 batman
和 robin
的情况,您可以这样做,例如:
git push robin robin-tall:tall
在这里,您在冒号:
的左侧写您的 分支名称,在右侧写他们的 分支名称。 (这里中间的 robin
是 remote: 您发送提交的 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关于远程分支--我的理解:远程分支永远是存储最新的版本。