变基出错后删除其他人在我的分支上的提交

Remove other peoples' commits on my branch after rebase gone wrong

我在这里陷入了一些 git-恐惧。我需要 git-fu 自己摆脱这个。

我加入了一个新团队并创建了一个功能分支:

git checkout -b feature_branch

进行了一些更改,然后 committed/pushed 将它们提交到分支。

git commit -am "Changes"
git push origin feature_branch

有人对我的 PR 进行了评论,所以我进行了更改,然后在 committing/pushing 之前检查了 master 并重新定位了我的分支:

// from feature_branch make some changes
git commit -am "New changes"
git checkout master
git checkout feature_branch
git rebase origin/master
git push feature_branch

执行此操作后,我注意到我的 PR(在 Github 上)获取了其他人的提交。然后我被告知,这个新团队中的典型方法是结帐到 master 并合并回我的分支而不是 rebase。

现在是时髦的部分——我开始研究 git reset --hard 并选择了我想要的提交,该提交是在其他人提交之前。

一切都很好,或者我是这么认为的。然后我把它推高了,它似乎已经从我的 PR 中删除了其他人的提交。

我今天早上检查过,现在有一堆来自其他人的其他提交被选中了。

所以现在我处于这种奇怪的状态。我查看了我的 PR,有将近 30 个提交(其中 6 个来自不同的人)。实际差异(文件更改)只是我接触的文件,这很好,但历史本身看起来很荒谬。

清理它的最佳方法是什么?一切都建议使用 git rebase,但是,我被建议不要使用 rebase。

不幸的是,我需要保留这个分支。清理它并删除除我之外的所有其他提交的最佳方法是什么?完全重置它,然后将更改挑选回分支?

请帮忙:|

编辑:这是历史记录的示例:

Commits on Jul 30, 2018
<SOMEONE ELSES>

Commits on Jul 31, 2018
<SOMEONE ELSES>
<MY ORIGINAL COMMIT>
<SOMEONE ELSES>

Commits on Aug 1, 2018
<SOMEONE ELSES>
<MY COMMIT [Merge branch master into my feature branch]>
<MY COMMIT>
<SOMEONE ELSES>
<MY COMMIT>
<MY COMMIT>
<SOMEONE ELSES>
<MY COMMIT>

etc etc

你清理东西的最佳选择可能是使用 git rebase -i 在你要清理的所有东西之前基于你分支1 中已经存在的先前更改向上,然后从编辑器的更改列表中删除您不想要的更改(只留下您想要的更改)。这将重写更改以仅包含您的更改并让您回到 "clean"(相对)状态。

完成后,您可以按照 git 流程的建议从主控(或任何地方)git merge


1可能是你最初分支的更改,如果你想清除你之前 rebased/merged 到你的分支的所有内容,或者可能是以后的一些参考点。您选择的点越早,您(可以)清理的东西就越多,但您需要做的工作也可能越多。

// from feature_branch make some changes
git commit -am "New changes"
git checkout master
git checkout feature_branch
git rebase origin/master
git push feature_branch

Once I did this, I noticed my PR (on Github) picked up someone elses' commit.

如果您所做的只是在 origin/master 之上进行变基,那应该是不可能的。

但是,这个序列有点可疑。你永远不会做 git fetch 所以 origin/master 不知道是最新的。如果确实发生了变基,git push feature_branch 应该会失败,因为无法快速转发变基。您将不得不使用 git push -f feature_branch.

我怀疑您没有向我们展示其他问题。完整的命令历史记录会有所帮助。

使用 rebase 更新分支的正确顺序是这样的。

# Update all your remotes
git fetch

# Rebase your branch on top of origin/master
git checkout feature_branch
git rebase origin/master

# Force push the branch
git push -f

幸运的是,你的旧提交在变基后并没有丢失,它们只是没有连接到任何东西。要找到它们,请使用 git reflog。这将在每次 HEAD(即您当前的结帐)更改时显示。

在 reflog 中,查找类似这样的内容...

081abed HEAD@{8}: rebase finished: returning to refs/heads/feature_branch
081abed HEAD@{9}: rebase: the last commit message from your branch
0a5b366 HEAD@{10}: rebase: another commit message
e9c4d18 HEAD@{11}: rebase: the first commit message from your branch
e6780bf HEAD@{13}: rebase: checkout origin/master
0ee63b1 HEAD@{14}: checkout: moving from master to feature_branch

0ee63b1 将是您的旧分支提示。 git reset --hard 0ee63b1 并且您已撤消变基。


还有另一种解释:您对错误的分支进行了 PR。仔细检查一下。

What's the best approach to clean this up? Everything is suggesting to use git rebase, however, I was advised not to use rebase.

即使团队自己不使用 rebase 工作流程,它也可能是 修复未合并分支的更好方法。只要您确定不 另一个正在使用 你知道 possible implications 如果 事实并非如此。

注意:我假设您的遥控器名为 origin 并且分支是 创建于 master。如果不是这种情况,只需将它们替换为 合适的。

在任何事情之前,隐藏所有修改(如果有的话):

git stash save

并结帐到您的分支机构:

git checkout mybranch

(推荐)使用临时标记按原样备份分支:

git tag mybranch_bkp_rebase

变基

,你可以变基到创建分支的地方,然后 删除提交与您的分支无关的行。

git rebase -i "$(git merge-base origin/master HEAD)"

有了这个,你的分支中剩下的唯一提交将是那些已经 当你创建分支时在那里,加上来自行的提交 没有被删除。

(可选)检查一切正常后,您可以变基到 当前 master:

git rebase origin/master

重置

如果你不想变基,你可以重置到以前已知的好 状态。这可能是您自己分支中的提交,它是 创建于或当前 master:

# Pick one
last_known_good_rev=hash_of_last_good_commit
last_known_good_rev="$(git merge-base origin/master HEAD)"
last_known_good_rev='origin/master'
git reset --hard "$last_known_good_rev"

然后用 git log 检查可能丢失的提交:

git log --oneline mybranch_bkp_rebase..HEAD

cherry-pick他们:

git cherry-pick hash1 hash2 hash3

如果您在分支上有多个自己的提交,您可以将所有提交变基并压缩到最新提交中,这会将所有更改放在分支的顶端,这将停止 GitHub 引入在您的提交之间发生的所有更改。

从那里你可以强制将变基分支推送到远程,它应该只显示你新压缩和变基的提交。