重新定基公共分支

重新定基公共分支

我无法理解如何使用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 书籍

我猜这有某种关联,如果没有,我很想知道为什么。上述场景与我描述的程序有什么关系在这篇文章中

答案1

您不想重新设置已推送到公共存储库的提交的原因是该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 与之前的日志命令不同。如果您将此更改提交到您的公共存储库,您现在有两个提交,它们完成了相同的工作,这会导致问题。

现在假设,您不是将 b1 重新定位到 master 之上,而是将 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也能帮助进一步阐明正在发生的事情。

答案2

虽然迟到了,但是这是给后人的答案:

git rebase旨在供本地使用。它重写历史记录,这允许非常好的“主线”,但在多用户环境中很危险

如果:

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

然后它可能这样做有意义强迫要重写的历史记录。执行 rebase 操作,然后:

git push -f 来源远程分支

如果任何这些假设没有得到满足,你可能会后悔这个行动:-)

阅读更多内容,请阅读此博客文章

相关内容