我正在挖掘一些使用git的生产脚本,并尝试理解这个命令:
git pull --rebase origin "${tag_or_commit}"
根据我在git pull
和git rebase
的文档中发现的内容,看起来永远的唯一内容应该是{{1} bash变量,必须是命令才能工作的分支名称。
对于给定标记或提交而不是分支,此命令将执行的操作是否存在记录的行为?我在哪里可以找到它?
答案 0 :(得分:1)
标记和分支实际上只是对提交的引用,主要区别是分支是指移动目标(该分支上的最新提交),而标记引用单个时间点提交,但最终它们是只是指向一个提交。
上面的postgis
变量可以重命名为tag_or_commit
,或者只是tag_or_branch_or_commit
。我认为变量名称有点误导/混淆。
我发现最常见的使用rebased来给出一个分支,这意味着将分支重新绑定到最近的提交。提供提交(或标记)将重新提交到该提交,而不再进一步。
所以上面的完整命令是从原点拉出来的,然后重新定位已经发生的提交,直到commit
指的是这一点。一个用例可能是你想要重新生成已发布到生产的内容,并且你有一个标签tag_or_commit
,那么如果你要执行:
production_release
您将获得git pull --rebase origin production_release
标记之前的所有提交,但不会更多。
答案 1 :(得分:1)
修改:根据您对上一个答案的评论,您只是遗漏了一件事:git rebase
步骤重新定义当前分支,无论您传递给git pull
的论点是什么。你可以跳过剩下的所有内容了!
它实际上在the git pull
documentation,但在典型的git文档方式中,使得更加混乱:
<的Refspec>可以命名任意远程引用(例如,标记的名称),甚至是具有相应远程跟踪分支的引用集合(例如,refs / heads / *:refs / remotes / origin / *),但通常它是远程存储库中分支的名称。
缺少的是“refspec”的完整定义以及git pull
运行的两个部分的详尽描述。不幸的是,对于第一部分,refspecs同时出现在fetch和push中,但在它们中表现不同。可以说,对于获取目的,通常只需命名远程存在的分支或标记,git fetch
将其复制到您自己的存储库,但将名称更改为远程跟踪分支,例如{ {1}},如果它是分支。对于标签,它保持名称不变。 (更准确地说,原始origin/master
在您的存储库中变为refs/heads/master
,而其refs/remote/origin/master
保留refs/tags/v1.2
。)
第二部分可能更容易一些:refs/tags/v1.2
收集一些标志并自行处理它们,并将其余部分传递给它的第一步git pull
。其中一个标记git fetch
收集的是git pull
,它告诉它使用--rebase
作为第二步。否则,它会查看是否已将其配置为自动使用git rebase
;如果没有,则默认使用git rebase
。
在这种情况下,如果标签名称为 git merge
,tag
将: 1
git pull
git fetch origin tag
如果需要,获取步骤将创建一个本地标记,如果需要,可以获取任何相应的提交和其他对象,或者如果您已经拥有标记,则只是一个美化的无操作。
第二步是特别令人困惑的一点。将标记名称传递给git rebase tag
作为其“上游”参数似乎很奇怪。然而,它是明确的,可以理解;如果您知道有关rebase的秘密,那么在the git rebase
documentation中也可以很好地描述这一点:它不会更改任何提交,它只是复制一些提交,然后重新指出你当前的分支。
首先,git获取当前分支中包含的提交列表, 2 ,不包括从命名上游可到达的任何提交:
git rebase
接下来,git进入一个新的匿名分支,从$ git rev-list tag..HEAD
参数标识的提交开始,或者如果没有--onto
,则由“upstream”参数标识提交。在这种情况下,没有--onto
,“上游”参数是一个标签,所以git可以简单地检查标签(它不完全 - 它使用一般用于分支名称的形式 - 但是它的效果相同)。
作为倒数第二步,rebase“重放”其ID在--onto
输出中的每个提交。从本质上讲,git cherry-将每个这样的提交选择到新的匿名分支中。
作为最后一步(如果一切顺利,或者你已完成并完成git rev-list
之后),git移动你在 3 上的分支指向通过复制所有要复制的提交进行的最终提交。假设您位于标记的提交git rebase --continue
“之前”的某个分支上,我们可以绘制最终结果的图形,如下所示:
T
此处 A - B - C [abandoned]
/
o - o - T - o - o <-- somebranch
\
A' - B' - C' <-- HEAD=yourbranch
到A
是您在C
步骤之前yourbranch
上的原始提交,而git pull origin tag
到A'
是他们的副本。
1 这仍然是简化的,C'
随着时间的推移而发展;实际的参数可能变得相当复杂。幸运的是,对于这个特殊情况,这些都不重要。
2 如果您根本没有分支,这甚至可以工作:在这种情况下,git使用由git pull
中的任何提交ID定义的匿名分支。
3 如果你不在分支机构,那就更容易了:它只是完全跳过这一步。 HEAD
仍然指向一个匿名分支,但现在它是复制的分支。