用Git重新定位

时间:2018-03-19 21:18:10

标签: git rebase git-rebase git-pull

我已经看了很多关于如何使用Git进行改组的文章,这是有意义的......或者至少我认为它确实如此。但是,我正在努力解决以下问题......

对于这种情况,我们有以下分支:

  • master(local)
  • 起源/主
  • jheigs(local)
  • 起源/ jheigs

好的,现在让我们说origin / master提前1次提交。所以,我从文章中得知,我正在开发的开发团队是在jheigs分支上做以下事情:

$ git add ...
$ git commit ...
$ git status (ensure everything is up-to-date locally)
$ git pull (again, check and ensure that everything is ready to go)
$ git pull --rebase origin master
$ git push (defaulting to origin/jheigs)
  1. 当rebase运行正常时,我遇到的是origin / jheigs和本地jheigs有HEAD提交不匹配(给定上面的rebase),所以有时我可能需要拉,然后推,这可能会导致冲突。我感到困惑的是......我应该使用:

    $ git push --force origin jheigs (?)
    
  2. 第二个问题......现在,让我们说我已经推动并且jheigs已经使用origin / master正确地重新定位了。没有冲突存在,我的jheigs和origin / jheigs现在领先于1次提交。好的,过了一天,我需要做出更多改变。所以我在jheigs上进行了这些更改并添加/ commit。但是,origin / master没有其他更新。从本质上讲,我仍然领先于origin / master的1次提交(很快就会是2次)。我仍然遵循上述相同的流程吗?或者我只是添加/提交并推送到origin / jheigs而不进行重新定位,因为我已经领先于origin / master?

  3. 我很抱歉这是如此之长,但我想我已经想到了这一点并且它不像我想象的那么顺利。我想小心变基础,所以感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

嗯,首先,我会(并且确实)完全避免git pull,或者大多数:它本来是方便的,但事实证明 方便。它只运行git fetch,然后是第二个Git命令,它会影响您检出的任何分支。有时我不想要或不需要取物;其他时候,我想环顾一下发生了什么 fetch运行时,之前我做任何第二个命令来影响当前分支。

正如您可能已经阅读过的那样,git rebase实际上是关于复制(某些)提交。你的存储库中有一些提交集合,现在,无论出于什么原因,一些提交都没有亮相,你想要做出更新,更好,更漂亮,更有光泽的提交。

使所有这些有意义的方法是绘制提交图。请记住,有多个克隆 - 不同的存储库包含大多数相同的提交集,但不完全相同的集合涉及!

绘制自己的存储库提交

您可以让Git为您执行此操作:git log --all --decorate --oneline --graph或git log(with)A DOG。不过,一开始手工做是很好的锻炼。此外,当你手工完成时,你可以水平绘制它们,这往往更有意义。

请记住,每个由其唯一哈希ID标识的提交都是只读的。每个提交都指向其提交。分支名称(如masterjheigs)或远程跟踪名称(如origin/masterorigin/jheigs指向(记录哈希ID) )提示提交,Git从这些提示向后工作:

...--C--D--E   <-- master
         \
          F--G   <-- jheigs (HEAD)

这可能是存储库的图形片段,其中提交Emaster的提示,而E指向D,而您是添加了两个自己的提交:G,这是jheigs的提示,并指向F,之前,您添加F指向{{1} }}

请注意,此处,提交D及更早版本位于两个分支上。

D会将 1 的一些提交复制到新的和改进的提交中。例如,您可能希望将git rebase复制到新的F,其主要区别在于F'附加到F',而不是E {1}}:

D

F' [new and improved!] / ...--C--D--E <-- master \ F--G <-- jheigs (HEAD) 复制到F后,您现在可以将F'复制到新版本G

G'

现在所有的提交都是&#34; on&#34; (可从 F'-G' [new and improved!] / ...--C--D--E <-- master \ F--G <-- jheigs (HEAD) 到达,但jheigs上的已被复制到新版本,您可以让Git剥离master标签关闭提交jheigs并将其粘贴到G

G'

旧的,沉闷的 F'-G' <-- jheigs (HEAD) / ...--C--D--E <-- master \ F--G [abandoned] F提交昨天如此闪亮和好看,现在是垃圾,取而代之的是闪亮的新GF'。这是因为您的分支名称G'现在指向最后一个新复制的提交。

1 此复制就像jheigs一样完成。根据您使用的rebase命令,实际上 可以使用git cherry-pick完成。

还涉及另一个存储库:git cherry-pickfetch

上图是您的存储库,但此处涉及第二个存储库。他们有自己的分支名称和他们自己的提交。您拥有的提交也是共享提交哈希ID。你可能会有一些他们不承认的承诺;可能会有一些他们认为你没有的承诺。

如果您认为他们可能会提交您的承诺,则应该运行pushgit fetch。这让你的Git在名为git fetch origin的名单下的URL中调用他们的Git。你的Git调用他们的Git并让他们列出他们的分支名称给出的所有提交(按哈希ID)。

如果他们有你没有的提交,你的Git现在会下载这些提交。您的Git也更改其分支机构名称,例如originmaster,以便他们阅读jheigsorigin/master。这些新名称不会干扰您的分支名称。

现在你已经拥有了他们拥有的所有提交,以及之前提交的所有提交,你的存储库可能看起来像这样 - 让我们假设你还没有完成origin/jheigs但是:

git rebase

您的 H <-- origin/master / ...--C--D--E <-- master \ F--G <-- jheigs (HEAD), origin/jheigs 是您的 分支机构名称的Git记忆。这意味着他们的 origin/*标识了提交master。您已经提交了H,感谢H他们的 git fetch标识提交jheigs,就像你的一样。

如果您现在运行G,您的Git会将您的git rebase masterF复制到新的GF',并在提交后生成G' {1}},这是E点的地方。您可能希望在提交master之后让它们出现。

在这里,您可以非常轻松地执行此操作:您只需运行H即可。这告诉你的Git找到你的git rebase origin/master提交的提交(即FG origin/master(即master无论如何,你可以记住)并在提交H之后放置副本。结果如下:

               F'-G'  <-- jheigs (HEAD)
              /
             H   <-- origin/master
            /
...--C--D--E   <-- master
         \
          F--G   <-- origin/jheigs

请注意,origin/*名称均未移动,您自己的master也未移动。但是,您调用jheigs他们的 origin/jheigs仍会记住提交G

现在您需要git push --force jheigs,告诉他们:丢弃提交FG,转而支持新的F'G'一旦他们同意这样做,你的Git会记住他们的jheigs指向G'

               F'-G'  <-- jheigs (HEAD), origin/jheigs
              /
             H   <-- origin/master
            /
...--C--D--E   <-- master

由于没有名称可以找到它们,因此提交FG似乎完全消失。

为什么你可能不想再改变

请注意,可能有第三个​​ Git存储库,第四个或更多存储库,其中包含另一个origin/jheigs。如果是这样,所有其他存储库必须采取某些操作(例如运行git fetch)以获取新提交并更新其自己的origin/jheigs名称。

此外,他们可能已经在您的提交之上构建了自己的提交,然后您决定抛弃您的提交以支持新的和改进的提交。如果是这样,他们可能会被迫复制他们的提交,就像您复制了他们一样。这甚至可能是一件好事,或者可能让他们恼火。

因此,如果您要重新提交其他人拥有或可能拥有的提交,您应该合理地确定为他们工作是可以的。如果没有其他人拥有原始提交,那么复制和替换它们显然是安全的。如果其他人都同意这种复制替换假设发生,那么它仍然没问题。如果这样做可以改变,那么这样做是否有意义。

答案 1 :(得分:0)

  

当rebase运行良好时,我遇到的是origin / jheigs和本地jheigs的HEAD提交不匹配(给定上面的rebase)

是的,但区别在于你额外的非推动工作。在git pull --rebase之后,上游HEAD将是您本地HEAD的祖先

  

因此有时我可能需要拉动然后按

这通常是正确的做法

  

可能会导致冲突。

它不应该,除非有人在你的拉动和推动之间推动(在这种情况下,你需要再次进行,以结合他们的工作)。

  

好的,过了一天,我需要做出更多改变。所以我在jheigs上进行了这些更改并添加/ commit。但是,origin / master没有其他更新。从本质上讲,我仍然领先于origin / master的1次提交(很快就会是2次)。我仍然遵循上述相同的流程吗?或者我只是添加/提交并推送到origin / jheigs而不进行重新定位,因为我已经领先于origin / master?

要么是好的。如果上游尚未移动,git pull --rebase将无效。