微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

由于不正确的变基,如何压缩重复提交? 如何在 beta/master 上重新设置 master如何在 beta/bootstrap 上重新设置 beta/master

如何解决由于不正确的变基,如何压缩重复提交? 如何在 beta/master 上重新设置 master如何在 beta/bootstrap 上重新设置 beta/master

由于我早期犯的错误并且当时没有解决我有一个特定的、复杂的 Git 情况。我将首先解释我采取的步骤(使用 Git 网络视觉效果)到达我的位置。

  1. 我从最初的 master 分支开始。

step-1

  1. 我创建了一个 new-catalog 分支并进行了一组提交 A

step-2

  1. 我使用过时的本地 new-catalog 重新定位 master,并拉入新的重新定位的 new-catalog 分支。 (虽然我当时不知道,但这将是我痛苦的开始)

step-3

这创建了第二组提交 A'A 相同,但具有新时间戳的不同提交。

step-3-context

  1. 我创建了一个 beta/master 分支(仍在过时的本地 master 之外),并将 new-catalog 推送到 beta/master

step-4

  1. 我在 B 上进行了另一组提交 beta/master

step-5

  1. 我从 beta/bootstrap 创建了一个子分支 beta/master

step-6

既然我在这里,我想将 beta/master 重新设置为 master,以准备 PR 回到 master。我确实尝试过变基,但是,我遇到了一些奇怪的冲突,我怀疑是由于重复的提交集 AA'。使用 beta/master 重新设置 master 的最安全方法是什么?

我已经考虑进行交互式变基并压缩/删除初始提交集 A,但我也不想丢失这些提交的时间信息。如果这是最好的选择,我愿意丢失时间信息,但我只是想看看有没有更好的方法

此外,如果我能够成功地对 beta/master 进行变基,是否还需要对 beta/bootstrap 进行变基?或者我可以在没有任何冲突的情况下 PR 到 beta/master 吗?

我做了一个 git-practice repository 来重现这些错误this 是整个网络。

非常感谢!

解决方法

使用 beta/master 重新设置 master 的最安全方法是什么?

我发现进行交互式 rebase 并删除初始提交集 A 是一种简化一切的安全方法。与我之前的想法相反,变基保留了作者时间戳(如使用 git log 时所见)并且仅替换提交时间步长(如在 GitHub 中所见)。

如何在 beta/master 上重新设置 master

  1. git checkout beta/master

    检查 beta/master 分支。

  2. git rebase -i master

    beta/master 上以交互方式重新设置 master

  3. 删除原始提交集 A

    在文本编辑器中用 pick 替换原始集合 d 中的每个提交的 A。对于我的 git-practice 存储库,这将是提交 3e8c537642dc347e2fa44b40f340

    然后,保存并退出编辑器。

  4. 处理任何合并冲突

    然后 Git 会将 beta/master 中的每个提交(从分支底部/最深的父提交开始)与 master 的 HEAD 进行比较。

    如果您遇到任何合并冲突,则顶部更改将是 master 分支(您要变基到的分支)的 HEAD 中的当前代码,底部更改将是与该提交对应的代码更改与 HEAD 冲突。您可以选择顶部更改、底部更改、两者兼而有之。

    在获得所需的文件后,请确保保存文件并git add 以暂存更改。然后,git rebase --continue 继续。

    如果你合并所有的冲突,它应该成功rebase并显示Successfully rebased and updated refs/heads/beta/master.

  5. git push --force origin beta/master

    这将推送您的本地 beta/master 并覆盖您的远程 origin/beta/master

我是否也需要对 beta/bootstrap 进行变基?或者我可以在没有任何冲突的情况下 PR 到 beta/master 吗?

您可以 PR(合并提交)到 beta/master,但变基会大量清理提交历史。

如何在 beta/bootstrap 上重新设置 beta/master

  1. git checkout beta/bootstrap

    检查 beta/bootstrap 分支。

  2. git rebase --onto beta/master beta/master@{1} beta/bootstrap

    beta/bootstrap 上重新设置 beta/master

  3. git push --force origin beta/bootstrap

    这将推送您的本地 beta/bootstrap 并覆盖您的远程 origin/beta/bootstrap

,

我不确定我是否理解正确。但我尝试在本地重现该问题并修复它。我使用了你的 git-practis 存储库。

我将本地主分支重置为提交 fb90356(我模拟中断主分支)并创建“new-catalog-demo”分支。

这是两次更改后的样子

[u@d git-practice]$ git reset --hard fb90356
HEAD wskazuje teraz fb90356 Add JavaScript
[u@d git-practice]$ git log -1
fb90356 Add JavaScript
[u@d git-practice]$ git checkout -b new-catalog-demo
Przełączono na nową gałąź „new-catalog-demo”
[u@d git-practice]$ git commit -a -m"Add feature 1"
[new-catalog-demo 5c91e3d] Add feature 1
 1 file changed,2 insertions(+),1 deletion(-)
[u@d git-practice]$ git commit -a -m"Add feature 2"
[new-catalog-demo ed804d5] Add feature 2
 1 file changed,2 insertions(+)
[u@d git-practice]$ git log --oneline --graph 
* ed804d5 (HEAD -> new-catalog-demo) Add feature 2
* 5c91e3d Add feature 1
* fb90356 (master) Add JavaScript
* a0f3d5a Add another main feature

然后我确实重新定位到中断主服务器并从原点/主服务器拉取。这是它之后的样子。与此同时,我将 master 重置为另一个提交以模拟来自另一方的一些更改。在第二个日志中,我们可以看到 A',B' 提交。

[u@d git-practice]$ git rebase master 
Pomyślnie przestawiono i zaktualizowano refs/heads/new-catalog-demo.
[u@d git-practice]$ git log --oneline --graph 
* c3f9338 (HEAD -> new-catalog-demo) Add feature 2
* 5ddb34c Add feature 1
* b89ef1b (master) Change another feature
* e7278df Change a main feature
* fb90356 Add JavaScript
* a0f3d5a Add another main feature
* 5a7b447 Add main feature
[u@d git-practice]$ git pull origin master
[u@d git-practice]$ git log --oneline --graph 
*   3b9619e (HEAD -> new-catalog-demo) Merge branch 'master' of https://github.com/itsjoshthedeveloper/git-practice into new-catalog-demo
|\  
| * b4bf1c6 (origin/master,origin/HEAD) Update main feature
| * f716c02 Change another main feature #-->> B' ??
| * f4f9669 Change main feature         #-->> A' ??
| * 98acbf4 Reset changed features
* | c3f9338 Add feature 2
* | 5ddb34c Add feature 1
|/  
* b89ef1b (master) Change another feature
* e7278df Change a main feature
* fb90356 Add JavaScript
* a0f3d5a Add another main feature
* 5a7b447 Add main feature
* ec699c4 Update README
* 395a5c6 Add h1
* e1633b3 Add index.html
* f11b51f Initial commit

我想我重现了你的问题。这是我修复它的方法

首先,我们必须检查 git reflog 以找到位置,在不适当的 rebase 之前,我们有 new-catalog-demo 分支进行了更改。

[u@d git-practice]$ git reflog 
3b9619e (HEAD -> new-catalog-demo) HEAD@{0}: pull origin master: Merge made by the 'recursive' strategy.
c3f9338 HEAD@{1}: rebase (finish): returning to refs/heads/new-catalog-demo
c3f9338 HEAD@{2}: rebase (pick): Add feature 2
5ddb34c HEAD@{3}: rebase (pick): Add feature 1
ed804d5 HEAD@{8}: commit: Add feature 2
5c91e3d HEAD@{9}: commit: Add feature 1
fb90356 HEAD@{10}: checkout: moving from master to new-catalog-demo
fb90356 HEAD@{11}: reset: moving to fb90356
b4bf1c6 (origin/master,origin/HEAD) HEAD@{12}: clone: from https://github.com/itsjoshthedeveloper/git-practice.git

我发现 new-catalog-demo 上最后一次好的提交是 ed804d5,所以我重新设置到这一点。

u@d git-practice]$ git reset --hard ed804d5
HEAD wskazuje teraz ed804d5 Add feature 2

现在我有我的 new-catalog-demo 分支和我的 ole 更改,然后我将它重新基于中断主

[u@d git-practice]$ git log --oneline --graph 
* c3f9338 (HEAD -> new-catalog-demo) Add feature 2
* 5ddb34c Add feature 1
* b89ef1b (master) Change another feature

不,我们可以将其发布到 origin/master 以确保我们在 master 分支的当前状态下执行此操作。

[u@d git-practice]$ git rebase origin/master 
Pomyślnie przestawiono i zaktualizowano refs/heads/new-catalog-demo.
[u@d git-practice]$ git log --oneline --graph 
* 86a2a81 (HEAD -> new-catalog-demo) Add feature 2
* 3dca49f Add feature 1
* b4bf1c6 (origin/master,origin/HEAD) Update main feature
* f716c02 Change another main feature

最后我们可以将 new-catalog-demo 合并到本地 master。

[u@d git-practice]$ git checkout master 
Przełączono na gałąź „master”
Twoja gałąź jest za „origin/master” o 4 zapisy i może zostać przewinięta.
  (użyj „git pull”,aby zaktualizować lokalną gałąź)
[u@d git-practice]$ git merge new-catalog-demo 
Aktualizowanie b89ef1b..86a2a81
Fast-forward
 README.md      | 5 ++++-
 web/index.html | 2 +-
 2 files changed,5 insertions(+),2 deletions(-)
[u@d git-practice]$ git log --oneline --graph 
* 86a2a81 (HEAD -> master,new-catalog-demo) Add feature 2
* 3dca49f Add feature 1
* b4bf1c6 (origin/master,origin/HEAD) Update main feature
* f716c02 Change another main feature
* f4f9669 Change main feature
* 98acbf4 Reset changed features
* b89ef1b Change another feature
* e7278df Change a main feature
* fb90356 Add JavaScript
* a0f3d5a Add another main feature
* 5a7b447 Add main feature
* ec699c4 Update README
* 395a5c6 Add h1
* e1633b3 Add index.html
* f11b51f Initial commit

现在历史是干净的,我们没有错过任何更改,也没有重复提交。我希望您现在了解如何使用 git reflog 解决此类问题。

,

没有“奇怪的冲突”,这只是变基的效果。甚至不考虑重复提交,因为已经合并到 beta/master 分支。正如您所注意到的,您的存储库有点混乱,但您仍然可以轻松(可能不会很快)达到所需的状态。问题是您在将更改合并到 master 之前等待的时间太长,具有冗余提交的副作用:除了重复的 new-catalog 分支之外,合并的拉取请求提交实际上是一个快进来自new-catalog。你可以自己验证你对同一棵树有多次提交:我在说

| * ec73ee6 Merge pull request #4 from itsjoshthedeveloper/new-catalog
|/| 
| *   84aabf5 Merge branch 'new-catalog' of https://github.com/itsjoshthedeveloper/git-practice into new-catalog
| |\  
| | * b40f340 Add a new JS feature
| | ...
| | ...
| | ...
| * | 4b463f5 Add a new JS feature

为了消除任何疑问,您可以很容易地找到哪个是 rebase 过程开始使用 git log $(git merge-base master beta/master) -n 1 --format="%h %s" 的公共根,它返回

f4f9669 Change main feature

当您在 beta/master 上变基 master 时出现的冲突来自您在 beta/master 上的整个 web/index.html 分支中所做的更改。最后一个文件在原始 master 中也已更改,这是您冲突的原因,而不是重复的 new-catalog。那么,一般该怎么做呢? 这是一个困境:git merge 获取分支的提示和最近的公共根,它尝试将它们合并在一起并创建提交(除非指定 --no-commit),除非不存在冲突,“简单”那样。另一方面,使用 git rebase 您可能有更多的冲突需要解决,这是由每次提交的投影 (cherry-pick) 引起的,从一个新的基础开始,但以线性历史结束.建议您只在频繁集成变更时选择第二种方式,尽可能避免多个分支之间的冲突。


关于 beta/bootstrap 分支,查看您在那里所做的更改,基于 beta/mastermaster 的变基不应产生任何冲突。但是,对您来说,首先在 beta/bootstrap 上重新设置 beta/master,然后在 beta/bootstrap 上重新设置(或在此之前进行合并)master 肯定更方便。通过这种方式,只需一次 rebase,您就可以将他们的两个技巧都推进。

甚至考虑使用 rerere:您似乎陷入困境,因为您有太多的冲突要解决。 git rerere 是一个非常有趣的功能,它包括缓存您如何解决某个冲突。假设您完成了一次合并,但最终您决定进行 rebase 并从零开始:一些冲突会自动解决,因为它们与之前遇到的相同。


编辑: 来自评论:

我首先尝试在 beta/bootstrap 上重新设置 beta/master,但是在 beta/master 上重新设置 master 之后,我不得不在 beta/bootstrap 上重新设置 beta/master再次

当然,您每次只能重新设置一个分支,即使它们共享大部分历史记录。为避免 rebase --onto,您可以在 beta/bootstrap 上重新设置 beta/master,在 beta/bootstrap 上重新设置下一个 master。此时,beta/bootstrap 分支同时具有 master 分支和 beta/master 提交作为其祖先。要将 beta/master 分支移动到 master 主线上的新提交,您必须使用诸如 git branch -f beta/master beta/bootstrap~2 之类的东西来强制它。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。