Git 找到第一个非本地提交
Git find first non-local commit
相关:List Git commits not pushed to the origin yet
git rev-parse HEAD
给我工作区中的最新提交,但这可以是本地提交的 githash。换句话说,尚未推送到远程的提交
如何找到工作区中远程也存在的最新提交
要获取当前签出分支的已配置远程分支的最新提交,请执行
# first get your remote-tracking branches up-to-date with remote
git fetch
# then do
git rev-parse @{upstream}
# or even just
git rev-parse @{u}
(注意:@{upstream} / @{u}
是 不是 占位符,它们应该按原样输入)
来自doc :
[<branchname>]@{upstream}, e.g. master@{upstream}, @{u}
The suffix @{upstream} to a branchname (short form @{u}) refers to the branch that the branch specified by branchname is set to build on top of (configured with branch..remote and branch..merge). A missing branchname defaults to the current one.
从技术上讲,git rev-parse HEAD
为您提供 当前 提交的哈希 ID。这不一定是 latest,即使在正常使用中它也不需要与工作树中的内容匹配(因为工作树可以修改但尚未提交)。这些要点也会干扰您按要求回答问题:也许您不想要 latest 提交。此外,您可以 git push
访问的某些远程存储库中的提交通常不在 任何 工作树中,因为此类远程存储库通常是 bare 存储库:.
除此之外,您可能想要的很简单:
git rev-parse origin/master
或:
git rev-parse origin/<some-other-name-here>
或:
git rev-parse @{upstream}
最后一项需要进一步解释。前两个简单地使用您现有的名称,在您现有的 Git 存储库中,以与 git rev-parse HEAD
相同的方式查找哈希 ID,尽管通常 less 复杂.
您的本地 Git 存储库可能 已过时 相对于另一个(远程) Git 存储库。在这种情况下,您可能需要 运行:
git fetch origin
首先是为了获得他们拥有的任何新提交,并更新您的各种 remote-tracking 名称: 名称如 origin/master
和 origin/develop
等等。
这是怎么回事
Git 将 分支名称 定义为一个名称——如 master
或 main
,或 develop
,或 feature/tall
或其他什么——保存此存储库中某些现有有效提交的哈希 ID。1 根据定义,该哈希 ID 是 last 在该分支“上”提交。
Git 对此的处理本身有点复杂,但如果我们注意到大多数提交——所有 普通 2—为它们的直接 parent 提交准确存储 one 哈希 ID,我们发现我们可以将提交彼此相邻放置,如珍珠或串珠:
... <-F <-G <-H ...
在这里,H
代表一些现有提交的哈希 ID。该提交存储其父(较早)提交的哈希 ID G
。提交 G
依次存储 still-earlier 提交 F
的哈希 ID,依此类推。
因为无法更改提交,并且哈希 ID 不可预测,3 这些箭头始终指向后方。 分支名称然后指向链中的最后一次提交:
...--G--H <-- main
此外,Git 进行设置,以便当您使用 git checkout
或 git switch
时 select 一些分支名称作为 当前分支,特殊名称 HEAD
附加到 分支名称:
...--G--H <-- main (HEAD)
此时,git rev-parse main
和git rev-parse HEAD
都会产生相同的哈希ID,即提交H
.
如果您添加一个 new 提交,Git 通过写出该提交的快照和元数据并使元数据包含 H
来构建新提交] 的哈希 ID,以便新提交 I
向后指向现有提交 H
:
...--G--H ...
\
I
然后,作为 git commit
的 last 步骤,Git 将 新提交的哈希 ID 写入任何名称 HEAD
附加到 ,给出:
...--G--H
\
I <-- main (HEAD)
名称 HEAD
仍然附加到名称 main
,但名称 main
现在表示提交 I
是 最后一个 在分支上提交。
然而,Git 确实有一种称为 detached HEAD 模式的模式。在这里,我们告诉 Git 到 select 通过分支名称以外的其他内容进行一些提交。例如,我们可能希望查看提交 G
的快照,因此 运行 git checkout <em>hash-of-G</em>
或类似的。结果是:
...--G <-- HEAD
\
H--I <-- main
git rev-parse HEAD
命令现在显示提交 G
的哈希 ID:不是提交 H
的哈希 ID,不是提交 I
的哈希 ID,而是提交 H
。那是因为 HEAD
不再 attached (分支名称),而是 detached (意思是 HEAD
包含直接提交的哈希 ID)。
(要返回提交 I
并在分支 main
上,我们将使用 git checkout main
或 git switch main
。这些将 re-attach HEAD
.)
1除非您的存储库已损坏,否则不会存在现有但无效的提交。这里的想法是强调,尽管哈希 ID 看起来 像随机垃圾,但您不能随便编一个。它们实际上是 hexadecimal 由 运行 加密校验和生成的大量数字的表示,因此它们根本不是随机的。
2这里ordinary commit的定义是存储一个parent hash ID。 merge commit的定义是存储两个或多个parent hash ID的commit,而Git还有第三种commit,一个root commit,存储 no paret 哈希 ID。根提交——在 non-empty、non-shallow 存储库中总是至少有一个提交——通常是某人为该存储库所做的第一个提交。可能有意或无意地进行更多的 root 提交,但很少有 good 这样做的理由;它只是脱离了 Git 使用的图形算法。
3为了让它像这样工作,Git 在每个提交中添加了一些独特的东西。特别是,每个提交都有一个 time-stamp,并且在正常使用中很难预测某些 future[=]time-stamp 的 future[=]future 提交将是。有一些理论上的方法可以在这里引起问题,但即使用作恶作剧也不切实际,至少在今天是这样。
更新名称,包括 git push
分支 名称特定于每个Git 存储库。您的 Git 存储库包含 您的 分支名称。其他一些 Git 存储库有 自己的 分支名称。
当你创建一个分支名称时,你只需为它选择一些现有的提交:
...--G--H <-- main (HEAD)
可能会变成:
...--G--H <-- develop (HEAD), main
您已经创建了新名称 develop
并为该名称选择了现有提交 H
。如果您现在进行新提交 I
,结果包括更改存储在 develop
中的哈希 ID,以生成:
...--G--H <-- main
\
I <-- develop (HEAD)
请注意,这次移动的是名称 develop
,因为 HEAD
附加到 develop
,而不是 main
。
任何可以直接访问存储库的人都可以随时创建或销毁分支名称,使用 git branch
(可能 -D
删除),或 git checkout -b
或 git switch -c
。他们还可以随时创建新的提交。
不过,每次提交都会获得一个唯一哈希ID。一旦你创建了一些提交集,你就可以使用 git push
将这些提交 发送 到其他一些 Git。他们完全按原样获取整个提交(每个提交的完整快照和元数据),并且他们计算相同的加密校验和,因此他们为这些相同的提交分配与您的 Git 分配给它们相同的哈希 ID。
通过使用这个原则,两个 Git 实际上设法通过查看 哈希 ID 来找出谁提交了哪个。这就是 Git 存储库的分布式特性。魔术真的全在散列中。
但是有一个问题。正如您自己的 Git 使用某个分支名称找到您的 最新 提交一样,他们的 Git 使用 他们的 找到最新提交 他们的 分支名称。因此,如果您要将提交 I
发送到其他 Git 存储库,请在 origin
处发送:
git push origin develop
在你这边,他们 将不得不在 他们的 存储库中设置一些分支名称。按照惯例——because humans are so easily fooled——我们倾向于在他们的仓库和我们的仓库中使用相同的分支名称。所以上面的git push
要求他们设置他们的develop
.
如果 develop
是一个 new 名字就没问题。如果我们不打算 丢失他们的任何提交 ,我们也可以要求他们设置他们的 main
。也就是说,假设他们有:
...--G--H <-- main
我们可以要求他们将 main
设置为指向某个新提交 J
,只要 J
最终指向 H
(可能通过 I
):
...--G--H <-- main
\
I--J <-- request: please make "main" go here
Git 将这种请求称为 fast-forward 操作 并且通常允许它。 (许多 add-on 网站,如 GitHub 添加了更高级的分支保护系统,让您更加挑剔;不过,此 fast-forward 检查是基础 Git 中内置的全部内容。)什么基础 Git 不会让你做的是这样的:
...--G--H--I <-- main
\
J <-- request: please make "main" go here
因为如果 他们 这样做,他们 将无法访问他们的提交 I
。
Remote-tracking 姓名和 git fetch
要解决此类问题,我们应该先使用 git fetch
,然后再使用 运行 git push
。当我们 运行 git fetch
时,我们的 Git 调用他们的 Git——就好像 git push
,我们会向他们发送我们的新提交——但不是发送提交给他们,我们Git向他们Git询问任何new-to-us 提交。他们发送这些——连同关于他们的哪个分支名称指向哪个提交的信息——我们的Git现在有任何新的提交他们有,那个我们不会。
让我们假设我们的 main
上都有 ...-G-H
,并且 他们 从某个地方获得了一些新的提交 I
。不过,与此同时,我们在 main
上添加了一个新提交 J
*。所以我们的起点是一样的:
...--G--H <-- main
但从那时起,他们 添加了 I
:
I <-- (main in their Git)
/
...--G--H
我们添加了J
:
...--G--H
\
J <-- main (in our Git)
当我们运行git fetch
时,我们拾取thir 新提交:
I <-- (main in their Git)
/
...--G--H
\
J <-- main
我们的 Git 无法更新我们的 main
因为如果更新了,我们将丢失我们自己的提交 J
. 所以我们的 Git 所做的——不管他们是否添加了任何 new 提交——是取他们的 branch 名称,main
,并改变它。我们的 Git 将他们的 branch 名称变成 remote-tracking 名称,方法是在其前面加上 origin/
。 4 所以我们最终得到:
I <-- origin/main
/
...--G--H
\
J <-- main
(注意:如果我们将 HEAD
作为当前的 checked-out 分支,请将 HEAD
添加到我们的 main
中。
这 git fetch
步骤:
- 获取他们拥有的所有新提交;
- 更新我们所有的remote-tracking名字;因此
- 让我们准备好做任何必要的事情来加入新的提交行(变基或合并)。
这意味着在 git fetch
之后跟进 git rebase
或 git merge
通常是明智的。 Git 提供了一个方便的命令,git pull
,它结合了这两个操作。由于多种原因,我不喜欢它,并鼓励 Git 的新手使用单独的 fetch
和 second-Git-command 序列,至少在他们非常熟悉整个过程之前。5
无论如何,所有这一切的总结是一个remote-tracking名称是Git记住其他Git存储库的方式在它的分支名称中,我们的 Git 最后一次与他们的 Git. 交谈 git fetch
操作倾向于更新所有这些,而 git push
操作在成功推送到一个分支时更新 one 。我们的 Git 从他们的 Git 那里得到确认他们接受了我们的请求,所以我们的 Git 现在知道他们的 Git 已经将那个名字设置为那个哈希 ID。6
4从技术上讲,remote-tracking 名称位于单独的 namespace 中,因此即使我们不小心调用了(本地)分支 origin/xyz
, Git 将能够根据他们的 xyz
分支。但这可以追溯到愚蠢的人类把戏,这让机器人班德发笑;不要那样做。
5并不是每个人都对git pull
如此谨慎。我不喜欢它的部分原因是它在早期有一些非常严重的错误,我不止一次因为 git pull
而失去了很多工作。但在我看来,主要问题是它做的太多了。正在采取行动使 git pull
在默认情况下表现得更好,尽管我不确定这在短期内发生的可能性有多大。如果它真的发生了,我仍然会推荐单独的步骤,但不会很快建议新手 避免 git pull
:这将是一个命令,如果它有效,它就做了正确的事情,如果没有,那就没有一件正确的事情。
6一些自动 fetch-time 更新是 Git 1.8.4 中的新功能,所以如果你有一个非常古老的 Git ,比这更早,请务必使用 git fetch origin
无限制地更新所有内容。在这些古老的 Git 版本中,git pull
运行 的 git fetch
通常根本无法更新任何内容(另一个要警惕 git fetch
的原因。
分支机构、上游和@{upstream}
允许但不要求每个分支名称具有一 (1) 个 upstream 设置。通常,main
或 develop
等分支的上游设置设置为 origin/main
或 origin/develop
: remote-tracking name 在您自己的 Git 存储库中。
有了这个套装可以使用一些方便的物品。实际上从来 不需要 。而且,当您在自己的存储库中创建一个全新的分支名称时,不使用 remote-tracking 名称(该名称尚不存在,因为 origin
Git 还没有此分支), 还没有它的上游,你会想使用git push -u origin HEAD
或类似于create的分支。这将在本地创建适当的 remote-tracking 名称,并且 -u
将使您的 Git 将 remote-tracking 名称设置为分支的上游。
一旦你设置了一个上游,@{upstream}
后缀——从技术上讲,它是一个你可以附加到 any 分支名称的后缀——告诉 Git找到那个分支的 upstream。也就是说,master@{upstream}
是 origin/master
,假设您已将 master
的上游设置为默认值 origin/master
。这对每个分支名称重复。
光秃秃的 @{upstream}
文字,就是这样写的,“意味着”HEAD@{upstream}
。所以这使用 HEAD
来确定你 在 上的哪个分支,然后使用分支的上游设置来确定你自己使用哪个 remote-tracking 名称本地 Git 存储库。
以上就是为什么以及如何 是这个的简短版本。 :-)
相关:List Git commits not pushed to the origin yet
git rev-parse HEAD
给我工作区中的最新提交,但这可以是本地提交的 githash。换句话说,尚未推送到远程的提交
如何找到工作区中远程也存在的最新提交
要获取当前签出分支的已配置远程分支的最新提交,请执行
# first get your remote-tracking branches up-to-date with remote
git fetch
# then do
git rev-parse @{upstream}
# or even just
git rev-parse @{u}
(注意:@{upstream} / @{u}
是 不是 占位符,它们应该按原样输入)
来自doc :
[<branchname>]@{upstream}, e.g. master@{upstream}, @{u}
The suffix @{upstream} to a branchname (short form @{u}) refers to the branch that the branch specified by branchname is set to build on top of (configured with branch..remote and branch..merge). A missing branchname defaults to the current one.
从技术上讲,git rev-parse HEAD
为您提供 当前 提交的哈希 ID。这不一定是 latest,即使在正常使用中它也不需要与工作树中的内容匹配(因为工作树可以修改但尚未提交)。这些要点也会干扰您按要求回答问题:也许您不想要 latest 提交。此外,您可以 git push
访问的某些远程存储库中的提交通常不在 任何 工作树中,因为此类远程存储库通常是 bare 存储库:
除此之外,您可能想要的很简单:
git rev-parse origin/master
或:
git rev-parse origin/<some-other-name-here>
或:
git rev-parse @{upstream}
最后一项需要进一步解释。前两个简单地使用您现有的名称,在您现有的 Git 存储库中,以与 git rev-parse HEAD
相同的方式查找哈希 ID,尽管通常 less 复杂.
您的本地 Git 存储库可能 已过时 相对于另一个(远程) Git 存储库。在这种情况下,您可能需要 运行:
git fetch origin
首先是为了获得他们拥有的任何新提交,并更新您的各种 remote-tracking 名称: 名称如 origin/master
和 origin/develop
等等。
这是怎么回事
Git 将 分支名称 定义为一个名称——如 master
或 main
,或 develop
,或 feature/tall
或其他什么——保存此存储库中某些现有有效提交的哈希 ID。1 根据定义,该哈希 ID 是 last 在该分支“上”提交。
Git 对此的处理本身有点复杂,但如果我们注意到大多数提交——所有 普通 2—为它们的直接 parent 提交准确存储 one 哈希 ID,我们发现我们可以将提交彼此相邻放置,如珍珠或串珠:
... <-F <-G <-H ...
在这里,H
代表一些现有提交的哈希 ID。该提交存储其父(较早)提交的哈希 ID G
。提交 G
依次存储 still-earlier 提交 F
的哈希 ID,依此类推。
因为无法更改提交,并且哈希 ID 不可预测,3 这些箭头始终指向后方。 分支名称然后指向链中的最后一次提交:
...--G--H <-- main
此外,Git 进行设置,以便当您使用 git checkout
或 git switch
时 select 一些分支名称作为 当前分支,特殊名称 HEAD
附加到 分支名称:
...--G--H <-- main (HEAD)
此时,git rev-parse main
和git rev-parse HEAD
都会产生相同的哈希ID,即提交H
.
如果您添加一个 new 提交,Git 通过写出该提交的快照和元数据并使元数据包含 H
来构建新提交] 的哈希 ID,以便新提交 I
向后指向现有提交 H
:
...--G--H ...
\
I
然后,作为 git commit
的 last 步骤,Git 将 新提交的哈希 ID 写入任何名称 HEAD
附加到 ,给出:
...--G--H
\
I <-- main (HEAD)
名称 HEAD
仍然附加到名称 main
,但名称 main
现在表示提交 I
是 最后一个 在分支上提交。
Git 确实有一种称为 detached HEAD 模式的模式。在这里,我们告诉 Git 到 select 通过分支名称以外的其他内容进行一些提交。例如,我们可能希望查看提交 G
的快照,因此 运行 git checkout <em>hash-of-G</em>
或类似的。结果是:
...--G <-- HEAD
\
H--I <-- main
git rev-parse HEAD
命令现在显示提交 G
的哈希 ID:不是提交 H
的哈希 ID,不是提交 I
的哈希 ID,而是提交 H
。那是因为 HEAD
不再 attached (分支名称),而是 detached (意思是 HEAD
包含直接提交的哈希 ID)。
(要返回提交 I
并在分支 main
上,我们将使用 git checkout main
或 git switch main
。这些将 re-attach HEAD
.)
1除非您的存储库已损坏,否则不会存在现有但无效的提交。这里的想法是强调,尽管哈希 ID 看起来 像随机垃圾,但您不能随便编一个。它们实际上是 hexadecimal 由 运行 加密校验和生成的大量数字的表示,因此它们根本不是随机的。
2这里ordinary commit的定义是存储一个parent hash ID。 merge commit的定义是存储两个或多个parent hash ID的commit,而Git还有第三种commit,一个root commit,存储 no paret 哈希 ID。根提交——在 non-empty、non-shallow 存储库中总是至少有一个提交——通常是某人为该存储库所做的第一个提交。可能有意或无意地进行更多的 root 提交,但很少有 good 这样做的理由;它只是脱离了 Git 使用的图形算法。
3为了让它像这样工作,Git 在每个提交中添加了一些独特的东西。特别是,每个提交都有一个 time-stamp,并且在正常使用中很难预测某些 future[=]time-stamp 的 future[=]future 提交将是。有一些理论上的方法可以在这里引起问题,但即使用作恶作剧也不切实际,至少在今天是这样。
更新名称,包括 git push
分支 名称特定于每个Git 存储库。您的 Git 存储库包含 您的 分支名称。其他一些 Git 存储库有 自己的 分支名称。
当你创建一个分支名称时,你只需为它选择一些现有的提交:
...--G--H <-- main (HEAD)
可能会变成:
...--G--H <-- develop (HEAD), main
您已经创建了新名称 develop
并为该名称选择了现有提交 H
。如果您现在进行新提交 I
,结果包括更改存储在 develop
中的哈希 ID,以生成:
...--G--H <-- main
\
I <-- develop (HEAD)
请注意,这次移动的是名称 develop
,因为 HEAD
附加到 develop
,而不是 main
。
任何可以直接访问存储库的人都可以随时创建或销毁分支名称,使用 git branch
(可能 -D
删除),或 git checkout -b
或 git switch -c
。他们还可以随时创建新的提交。
不过,每次提交都会获得一个唯一哈希ID。一旦你创建了一些提交集,你就可以使用 git push
将这些提交 发送 到其他一些 Git。他们完全按原样获取整个提交(每个提交的完整快照和元数据),并且他们计算相同的加密校验和,因此他们为这些相同的提交分配与您的 Git 分配给它们相同的哈希 ID。
通过使用这个原则,两个 Git 实际上设法通过查看 哈希 ID 来找出谁提交了哪个。这就是 Git 存储库的分布式特性。魔术真的全在散列中。
但是有一个问题。正如您自己的 Git 使用某个分支名称找到您的 最新 提交一样,他们的 Git 使用 他们的 找到最新提交 他们的 分支名称。因此,如果您要将提交 I
发送到其他 Git 存储库,请在 origin
处发送:
git push origin develop
在你这边,他们 将不得不在 他们的 存储库中设置一些分支名称。按照惯例——because humans are so easily fooled——我们倾向于在他们的仓库和我们的仓库中使用相同的分支名称。所以上面的git push
要求他们设置他们的develop
.
如果 develop
是一个 new 名字就没问题。如果我们不打算 丢失他们的任何提交 ,我们也可以要求他们设置他们的 main
。也就是说,假设他们有:
...--G--H <-- main
我们可以要求他们将 main
设置为指向某个新提交 J
,只要 J
最终指向 H
(可能通过 I
):
...--G--H <-- main
\
I--J <-- request: please make "main" go here
Git 将这种请求称为 fast-forward 操作 并且通常允许它。 (许多 add-on 网站,如 GitHub 添加了更高级的分支保护系统,让您更加挑剔;不过,此 fast-forward 检查是基础 Git 中内置的全部内容。)什么基础 Git 不会让你做的是这样的:
...--G--H--I <-- main
\
J <-- request: please make "main" go here
因为如果 他们 这样做,他们 将无法访问他们的提交 I
。
Remote-tracking 姓名和 git fetch
要解决此类问题,我们应该先使用 git fetch
,然后再使用 运行 git push
。当我们 运行 git fetch
时,我们的 Git 调用他们的 Git——就好像 git push
,我们会向他们发送我们的新提交——但不是发送提交给他们,我们Git向他们Git询问任何new-to-us 提交。他们发送这些——连同关于他们的哪个分支名称指向哪个提交的信息——我们的Git现在有任何新的提交他们有,那个我们不会。
让我们假设我们的 main
上都有 ...-G-H
,并且 他们 从某个地方获得了一些新的提交 I
。不过,与此同时,我们在 main
上添加了一个新提交 J
*。所以我们的起点是一样的:
...--G--H <-- main
但从那时起,他们 添加了 I
:
I <-- (main in their Git)
/
...--G--H
我们添加了J
:
...--G--H
\
J <-- main (in our Git)
当我们运行git fetch
时,我们拾取thir 新提交:
I <-- (main in their Git)
/
...--G--H
\
J <-- main
我们的 Git 无法更新我们的 main
因为如果更新了,我们将丢失我们自己的提交 J
. 所以我们的 Git 所做的——不管他们是否添加了任何 new 提交——是取他们的 branch 名称,main
,并改变它。我们的 Git 将他们的 branch 名称变成 remote-tracking 名称,方法是在其前面加上 origin/
。 4 所以我们最终得到:
I <-- origin/main
/
...--G--H
\
J <-- main
(注意:如果我们将 HEAD
作为当前的 checked-out 分支,请将 HEAD
添加到我们的 main
中。
这 git fetch
步骤:
- 获取他们拥有的所有新提交;
- 更新我们所有的remote-tracking名字;因此
- 让我们准备好做任何必要的事情来加入新的提交行(变基或合并)。
这意味着在 git fetch
之后跟进 git rebase
或 git merge
通常是明智的。 Git 提供了一个方便的命令,git pull
,它结合了这两个操作。由于多种原因,我不喜欢它,并鼓励 Git 的新手使用单独的 fetch
和 second-Git-command 序列,至少在他们非常熟悉整个过程之前。5
无论如何,所有这一切的总结是一个remote-tracking名称是Git记住其他Git存储库的方式在它的分支名称中,我们的 Git 最后一次与他们的 Git. 交谈 git fetch
操作倾向于更新所有这些,而 git push
操作在成功推送到一个分支时更新 one 。我们的 Git 从他们的 Git 那里得到确认他们接受了我们的请求,所以我们的 Git 现在知道他们的 Git 已经将那个名字设置为那个哈希 ID。6
4从技术上讲,remote-tracking 名称位于单独的 namespace 中,因此即使我们不小心调用了(本地)分支 origin/xyz
, Git 将能够根据他们的 xyz
分支。但这可以追溯到愚蠢的人类把戏,这让机器人班德发笑;不要那样做。
5并不是每个人都对git pull
如此谨慎。我不喜欢它的部分原因是它在早期有一些非常严重的错误,我不止一次因为 git pull
而失去了很多工作。但在我看来,主要问题是它做的太多了。正在采取行动使 git pull
在默认情况下表现得更好,尽管我不确定这在短期内发生的可能性有多大。如果它真的发生了,我仍然会推荐单独的步骤,但不会很快建议新手 避免 git pull
:这将是一个命令,如果它有效,它就做了正确的事情,如果没有,那就没有一件正确的事情。
6一些自动 fetch-time 更新是 Git 1.8.4 中的新功能,所以如果你有一个非常古老的 Git ,比这更早,请务必使用 git fetch origin
无限制地更新所有内容。在这些古老的 Git 版本中,git pull
运行 的 git fetch
通常根本无法更新任何内容(另一个要警惕 git fetch
的原因。
分支机构、上游和@{upstream}
允许但不要求每个分支名称具有一 (1) 个 upstream 设置。通常,main
或 develop
等分支的上游设置设置为 origin/main
或 origin/develop
: remote-tracking name 在您自己的 Git 存储库中。
有了这个套装可以使用一些方便的物品。实际上从来 不需要 。而且,当您在自己的存储库中创建一个全新的分支名称时,不使用 remote-tracking 名称(该名称尚不存在,因为 origin
Git 还没有此分支), 还没有它的上游,你会想使用git push -u origin HEAD
或类似于create的分支。这将在本地创建适当的 remote-tracking 名称,并且 -u
将使您的 Git 将 remote-tracking 名称设置为分支的上游。
一旦你设置了一个上游,@{upstream}
后缀——从技术上讲,它是一个你可以附加到 any 分支名称的后缀——告诉 Git找到那个分支的 upstream。也就是说,master@{upstream}
是 origin/master
,假设您已将 master
的上游设置为默认值 origin/master
。这对每个分支名称重复。
光秃秃的 @{upstream}
文字,就是这样写的,“意味着”HEAD@{upstream}
。所以这使用 HEAD
来确定你 在 上的哪个分支,然后使用分支的上游设置来确定你自己使用哪个 remote-tracking 名称本地 Git 存储库。
以上就是为什么以及如何