重新分配公共分支


6

我无法理解如何使用 git-rebase,我考虑以下示例。

让我们开始一个存储库 ~/tmp/repo

$ git init

然后添加一个文件 foo

$ echo "hello world" > foo

然后添加并提交:

$ git add foo
$ git commit -m "Added foo"

接下来,我启动了一个远程存储库。在 ~/tmp/bare.git 我跑了

$ git init --bare

为了链接 repobare.git 我跑了

$ git remote add origin ../bare.git/
$ git push --set-upstream origin master

接下来,让分支,添加文件并为新分支设置上游 b1

$ git checkout -b b1
$ echo "bar" > foo2
$ git add foo2
$ git commit -m "add foo2 in b1"
$ git push --set-upstream origin b1

现在是时候切换回来了 master 并改变那里的东西:

$ echo "change foo" > foo
$ git commit -a -m "changed foo in master"
$ git push

在这一点上 master 文件 foo 包含 改变了foo , 而在 b1 它还是 你好,世界 。最后,我想要同步 b1 随着进步 master

$ git checkout b1
$ git fetch origin
$ git rebase origin/master

在此刻 git st 收益:

# On branch b1
# Your branch and 'origin/b1' have diverged,
# and have 2 and 1 different commit each, respectively.
#   (use "git pull" to merge the remote branch into yours)
#
nothing to commit, working directory clean

此时的内容 foo 在分公司 b1 改变foo 同样。那么这个警告意味着什么呢?我希望我能做到 git push,git建议做 git pull... 根据 这个答案 ,这或多或少都是这样,并且在他的评论中@FrerichRaabe明确地说我不需要做拉。这里发生了什么?危险是什么,应该如何进行?如何保持历史一致?上述案例与以下引文之间的相互作用是什么:

不要将已推送到公共存储库的提交重新绑定。

取自 亲git书

我猜它有点相关,如果不是,我很想知道为什么。上述场景与我描述的过程之间有什么关系 在这篇文章中


原因 git st 给出那个输出是因为git知道你的本地 b1 分支正在跟踪 origin/b1,这就是你想要改变的东西。你跑了 git rebase origin/master 但是,所以你重新定位(“重播”)你的 b1 提交在上面 origin/master
Frerich Raabe

@FrerichRaabe:让我试试改写。你说假设 origin/mastermaster 更新,我应该改变 origin/b1origin/master,然后呢 git pull 什么时候 b1 签出将rebase拉到本地存储库?
Dror

不,你不需要 git pull 并且你永远不会改变远程分支(例如 origin/master )其他任何事情。
Frerich Raabe

@FrerichRaabe那么这里的正确方法是什么?一个人的警告意味着在重组之后 origin/b1b1 不一样。这是相当明显的,但是解决它的正确方法是什么?或修复它意味着弄乱历史,如@heavyd所解释的那样?
Dror

1
只要一个回购是唯一一个从公共远程仓库推/拉的回购你是安全的,我会补充一下。我遇到了一些问题,我是唯一一个在项目上工作的人,但我在两台不同的机器上工作。如果分支机构在这种情况下发生分歧,你仍然可能会一团糟。
heavyd

Answers:


7

您不想重新提交已推送到公共存储库的提交的原因是因为 git-rebase 命令更改历史记录

现在,这意味着什么,为什么不好?首先,我建议阅读 这个部分 Git书。从中您将了解到,提交包含指向树对象的指针(文件的快照)和指向父提交的指针。现在,当您通过在新提交之上重新设置提交来“更改历史记录”时,您将更改已经提交的提交的父指针,这将改变提交的ID。

这很糟糕的原因是,如果您公开分享您的提交,而其他人根据这些提交开始额外的工作,那么您将更改这些提交,您的树不再同步。

你可以通过发一些来看到所有这一切 git-log 执行示例时的命令。我在运行rebase命令之前运行了这些:

$ git log --pretty=oneline origin/master
9b077261d1619803213201d5c7cefb757eb66b67 Changed foo in master
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

$ git log --pretty=oneline origin/b1
63a57ef54e301314a9dab38de0cd9d88c59a5fba added foo2 in b1
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

$ git log --pretty=oneline b1
63a57ef54e301314a9dab38de0cd9d88c59a5fba added foo2 in b1
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

现在,在执行rebase之后, origin/masterorigin/b1 是一样的,但是 b1 就是现在:

$ git log --pretty=oneline b1
6687c64c37db0ee21a4d87e45d6ccb0913b8686d added foo2 in b1
9b077261d1619803213201d5c7cefb757eb66b67 Changed foo in master
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

您会注意到“b1中添加的foo2”提交的ID与以前的日志命令中的ID不同。如果将此更改提交到公共存储库,则现在有两个提交在其中完成相同的工作并且会导致问题。

现在假设,不是在master上重新设置b1,而是将master合并到b1中,你的日志将如下所示:

$ git checkout b1
$ git merge origin/master
$ git log --pretty=oneline b1
518eb2dc6b2da0ff43ddd6837332031cc00eaad1 Merge remote-tracking branch 'origin/master' into b1
9b077261d1619803213201d5c7cefb757eb66b67 Changed foo in master
63a57ef54e301314a9dab38de0cd9d88c59a5fba added foo2 in b1
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

您将注意到代表两个先前提交的合并的额外提交。现在可以分享这段历史,每个人都会很开心。

git-log --graph 还可以帮助减少一些有关正在发生的事情的信息。


你能参考链接帖子中描述的方法吗?另外,如果发生了什么 我知道 那个 origin/b1 仅由我自己使用 - 假设它是某种备份 b1。这种假设对这种情况有什么影响?在这种情况下是否有意义 git push --force 在rebase之后还是类似的东西?
Dror

老实说,你的帖子中描述的工作流程是很多额外的工作。你应该能够通过运行来完成同样的事情 git merge master 当。。。的时候 foo 分支签出。再次,尝试自己使用 git-log 看看发生了什么。
heavyd

确实,但这种合并有一个很大的缺点 - 通常 master 被认为是一个稳定的分支,而 foo (或任何其他分支)是不稳定的。将稳定合并到不稳定中是不希望的,因此需要额外的工作。我想弄清楚是否有快捷方式。
Dror

1
你能解释为什么将稳定合并到不稳定中是不可取的吗?这不应该比已经破坏分支的稳定。
heavyd

也许“不受欢迎”的措辞过于强烈。如果你总是将unstable合并到stable中,那么当分支准备好并且对于它自己稳定时,它只有一个(!)合并回master。这产生了更清晰的历史。也许更好的措辞是这种方法具有上述优势。
Dror

3

晚会,但这是后人的答案:

git rebase 意在在当地使用。它重写历史,它允许一个非常好的“主线”,但在多用户环境中是危险的

如果:

  • 你是唯一一个使用远程存储库的人,
  • 并且您只在一个工作区中使用它,

然后呢 威力 有意义的做到这一点 迫使 要重写的历史。做你的rebase然后:

git push -f origin remotebranch

如果未满足任何这些假设,您可能会后悔这一行动:-)

阅读此博客文章中的更多内容

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.