简体   繁体   English

git pull --rebase原始标记名?

[英]git pull --rebase origin tagname?

I'm digging through some production scripts that use git, and trying to make sense of this command: 我正在研究一些使用git的生产脚本,并试图理解此命令:

git pull --rebase origin "${tag_or_commit}"

From what I'm finding in the documentation for git pull and git rebase , it looks like the only thing that should ever be in that tag_or_commit bash variable, would have to be a branch name for the command to work at all. 从什么我发现了文档中的git pullgit rebase ,它看起来像应该永远是在唯一tag_or_commit bash的变量,必须是一个分支名称为命令在所有的工作。

Is there documented behavior for what this command will do given a tag or commit instead of a branch? 给定标签或提交而不是分支的情况下,此命令将执行的操作是否有记录的行为? Where can I find it? 在哪里可以找到它?

A tag and branch are really just references to commits, with the main difference being a branch refers to a moving target (the latest commit on that branch), while a tag references a single point in time commit, but ultimately they are just pointing to a commit. 标签和分支实际上只是对提交的引用,主要区别是分支指向移动的目标(该分支上的最新提交),而标签则引用单个时间点提交,但最终它们只是指向一次提交。

The tag_or_commit variable above could be renamed tag_or_branch_or_commit , or simply commit . 上面的tag_or_commit变量可以重命名为tag_or_branch_or_commit ,或者简单地称为commit I would argue that the variable name is somewhat misleading / confusing. 我认为变量名有些误导/令人困惑。

I find the most common usage of rebasing it to give a branch, which means to rebase the branch to the most recent commit. 我发现将其重新建立基础以提供分支的最常见用法,这意味着将分支重新构建为最新的提交。 Providing a commit (or tag) will rebase up to that commit, and no further. 提供一个提交(或标记)将根据该提交进行基础,并且不再进行。

So the full command above is pulling from the origin, and then rebasing the commits that have happened up to the point that tag_or_commit is referring to. 因此,上面的完整命令是从原点开始的,然后根据已经发生的提交重新tag_or_commit引用的位置。 A use case might be if you wanted to rebase to what's been released to production, and you have a tag production_release , then if you were to execute: 一个用例可能是,如果您想基于已发布到生产环境中的内容,并具有一个标签production_release ,那么如果要执行:

git pull --rebase origin production_release

You would get all the commits up until the production_release tag, but no more. 您将获得所有提交,直到production_release标签为止,但没有更多。

Edit : based on your comments on the previous answer, you're just missing one thing: the git rebase step rebases the current branch , regardless of what arguments you've passed to git pull . 编辑 :根据您对上一个答案的评论,您只缺少一件事: git rebase步骤为当前分支重新设置基础 ,无论您传递给git pull参数如何。 You can probably skip all the rest of this! 您可能可以跳过所有其他操作!


It's actually in the git pull documentation , but in typical git documentation fashion, made extra-confusing: 它实际上在git pull文档中 ,但是以典型的git文档方式,使人更加困惑:

<refspec> can name an arbitrary remote ref (for example, the name of a tag) or even a collection of refs with corresponding remote-tracking branches (eg, refs/heads/*:refs/remotes/origin/*), but usually it is the name of a branch in the remote repository. <refspec>可以命名任意远程ref(例如,标记名称),甚至可以命名具有相应远程跟踪分支的ref集合(例如refs / heads / *:refs / remotes / origin / *),但是通常,它是远程存储库中分支的名称。

What's missing is a thorough definition of a "refspec" along with a thorough description of the two parts that git pull runs. 缺少的是对“ refspec”的详尽定义,以及对git pull运行的两个部分的详尽描述。 Unfortunately for the first part, refspecs appear in both fetch and push, but behave differently in them. 不幸的是,对于第一部分,refspecs出现在提取和推送中,但在它们中的表现却有所不同。 It may suffice to say that for fetch purposes, normally you just name a branch or tag that exists on the remote, and git fetch copies it to your own repository but changes the name to a remote-tracking branch, such as origin/master , if it's a branch . 可以说,出于获取目的,通常只需命名远程git fetch上存在的分支或标记,然后git fetch复制到您自己的存储库中,但将名称更改为远程跟踪分支,例如origin/master如果是分支 For tags, it leaves the name unchanged. 对于标签,它的名称保持不变。 (More precisely, origin's refs/heads/master becomes refs/remote/origin/master in your repository, while its refs/tags/v1.2 stays refs/tags/v1.2 .) (更确切地说,origin的refs/heads/master变为您存储库中的refs/remote/origin/master ,而其refs/tags/v1.2保留为refs/tags/v1.2 。)

The second part is perhaps a bit easier: git pull collects some flags and acts on them itself, and passes the rest of them to its first step, git fetch . 第二部分可能会更容易一些: git pull收集一些标志并对其进行操作,然后将其余标志传递到第一步git fetch One of the flags git pull collects is --rebase , which tells it to use git rebase as its second step. git pull收集的标志之一是--rebase ,它告诉它使用git rebase作为第二步。 Otherwise, it looks to see if it's been configured to use git rebase automatically; 否则,它会查看是否git rebase其配置为自动使用git rebase if not, it defaults to using git merge . 如果不是,则默认使用git merge

In this case, then, given a tag name tag , git pull will: 1 在这种情况下,给定标签名称taggit pull将: 1

  1. run git fetch origin tag 运行git fetch origin tag
  2. run git rebase tag 运行git rebase tag

The fetch step will create a local tag if needed, fetching any corresponding commits and other objects if needed, or just be a glorified no-op if you already have the tag. 提取步骤将在需要时创建一个本地标签,在需要时提取任何相应的提交和其他对象,或者如果已经有了该标签,则只是美化无操作。

The second step is the especially-confusing bit. 第二步是特别令人困惑的地方。 Passing a tag name to git rebase as its "upstream" argument seems weird. 将标签名称传递给git rebase作为其“上游”参数似乎很奇怪。 It is, however, well-defined and can make sense; 但是,它定义明确且有意义。 and this is also described reasonably well in the git rebase documentation , provided you know the secret about rebase: it doesn't change any commits, it just copies some commits, then re-points your current branch. 并且在git rebase文档中也对此进行了很好的描述,只要您知道有关rebase的秘诀:它不会更改任何提交,它只会复制一些提交,然后重新指向您的当前分支。

First, git gets a list of commits that are contained within the current branch, 2 excluding any commits reachable from the named upstream: 首先,git获取当前分支中包含的提交列表, 2排除从指定上游可到达的任何提交:

$ git rev-list tag..HEAD

Next, git gets onto a new anonymous branch starting with the commit identified by the --onto argument, or if there is no --onto , the commit identified by the "upstream" argument. 接下来,git进入一个新的匿名分支,该分支以--onto参数标识的提交开始,或者如果没有--onto--onto “上游”参数标识的提交开始。 In this case there is no --onto and the "upstream" argument is a tag, so git could simply check out the tag (it doesn't quite—it uses a general form that works for branch names as well—but it works out the same). 在这种情况下,没有--onto并且“ upstream”参数是一个标记,因此git可以简单地检出该标记(它并不完全—它也使用适用于分支名称的通用形式—但它可以正常工作一样)。

As its second to last step, the rebase "replays" each of the commits whose IDs are in the git rev-list output. 作为倒数第二步,rebase会“重播” ID在git rev-list输出中的每个提交。 Essentially, git cherry-picks each such commit into the new anonymous branch. 从本质上讲,git cherry-picks将每个此类提交提交到新的匿名分支中。

As the final step (if all has gone well, or after you've fixed things up and done git rebase --continue ), git moves the branch you were on 3 to point to the final commit made by coping all the to-be-copied commits. 作为最后一步(如果一切顺利,或者在完成所有工作之后, git rebase --continue ),git移动您所在的分支3指向通过应付所有待完成的最终提交复制的提交。 Assuming you were on a branch that originates somewhere "before" the tagged commit T , we can thus draw a graph of the final result like this: 假设您在一个分支上,该分支起源于被标记的提交T之前的某个地方,我们可以这样绘制最终结果的图形:

    A - B - C            [abandoned]
  /
o - o - T - o - o         <-- somebranch
          \
           A' - B' - C'   <-- HEAD=yourbranch

Here A through C are your original commits that were on yourbranch before the git pull origin tag step, and A' through C' are their copies. 这里AC是您在git pull origin tag步骤之前在yourbranch上的原始提交,而A'C'是它们的副本。


1 This is still simplified, and git pull has evolved over time; 1这仍然是简化的,并且git pull随着时间的推移而发展; the actual arguments can get pretty complex. 实际的参数可能会变得非常复杂。 None of that matters for this particular case, fortunately. 幸运的是,对于这个特殊情况,这些都不重要。

2 This even works if you're on no branch at all: in that case git uses the anonymous branch defined by whatever commit-ID is in HEAD . 2如果您根本不在分支上,这甚至可以工作:在这种情况下,git使用由HEAD任何commit-ID定义的匿名分支。

3 If you were not on a branch, that's even easier: it just skips this step entirely. 3如果您不在分支上,那就更容易了:它只是完全跳过了这一步。 HEAD still points to an anonymous branch, but now it's the copied one. HEAD仍指向一个匿名分支,但现在是复制的分支。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Git rebase local vs git pull --rebase origin - Git rebase local vs git pull --rebase origin “git pull origin develop --rebase”和“git pull --rebase origin develop”之间的区别 - Difference between 'git pull origin develop --rebase' and 'git pull --rebase origin develop' git pull --rebase 没有从原点拉取新文件 - git pull --rebase didn't pull new files from origin 为什么 git pull --rebase origin master 需要“master”,但 git rebase -i origin 不需要? - Why is "master" required in git pull --rebase origin master but not git rebase -i origin? 为什么git pull origin development不进行-rebase会导致冲突? - Why does git pull origin develop --rebase cause conflict when git pull origin develop doesn't? git pull --rebase origin master 后构建错误“找不到文件” - Build error “file not found” after git pull --rebase origin master 如何重新设置为master而不是git pull origin master? - How to rebase to master instead of git pull origin master? git pull --rebase origin master是什么意思? - What does git pull --rebase origin master means? 功能分支上的`git pull --rebase`合并到原点/主更改中 - `git pull --rebase` on feature branch to merge in origin/master changes `git pull origin main --rebase`,同时也更新本地的 `main` 分支 - `git pull origin main --rebase`, but also update local `main` branch
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM