git - 从合并分支中删除提交
git - remove commits from merged branch
我不小心推送了一些大文件的提交,然后将其还原。但这会导致任何拉动此分支的人都在历史记录中获取这些文件,因此我决定删除或压缩这两个提交。但是,合并了一些分支。我不知道如何"git rebase -i"保持分支结构。
历史现在看起来像:
H - new commits
|
G - merge
| \
| F - commits on another branch
| |
E | - some other commits
| |
D | - corrected B
| |
C | - revert B
| |
B | - huge files
| /
A - early commit
可以改成关注吗?
h - new commits
|
g - merge
| \
| F - commits on another branch
| |
e | - some other commits
| |
d | - corrected B
| /
A - early commit
不,你不能。
每个提交的哈希值不仅包括索引中所有文件的哈希值,还包括提交的 parents.
的哈希值
"Corrected B" 将会有一个与现在不同的 parent。那会改变散列。
可以修复此问题,但无法避免 force-pushing 修复,并在完成后让每个人 force-pull 它。
解决此问题的唯一真正方法是以下过程:
git checkout A
在分支分支之前检查 parent 提交。然后,创建两个工作分支:
git checkout -b corrected-mainline
git checkout -b corrected-fork
您现在位于 corrected-fork 分支。现在,在这个分支上,您应该能够 git cherry-pick
直到 F
提交的所有提交,跳过带有大文件的提交及其还原。如果这些提交中的任何一个是合并,则执行相同的合并。
现在,在 corrected-mainline
分支上做同样的事情
git checkout corrected-mainline
现在,git cherry-pick
主线分支上的所有提交,直到 G
合并之前的最后一次提交。然后,与 corrected-fork
分支合并。现在这是您更正的 G
合并提交。
完成 cherry-picking 图表中最初位于 G
之上的所有提交,以原始分支上的最后一次提交结束。
此时,你的工作分支的内容应该和你原来的分支的内容是一样的。验证是这样。
然后,删除您原来的分支,将您的工作分支重命名为它的名称。或者,使用 git reset --hard
将您的原始分支重置为更正后的工作分支。
然后执行 git push --force
,将您更正的分支向上推。当然,任何拉动分支的人最终都会得到 force-pull.
是的你可以但你不应该。
会要求你重写历史,替换掉服务器上已经推送的历史(需要强行推送,经常会被大家骂).
但如果您真的想要,那么 git filter-branch
就是您想要使用的,就像 this SO answer 中一样。所以你会做这样的事情:
git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = "<your commit to remove here>" ]
then
skip_commit "$@";
else
git commit-tree "$@";
fi' HEAD
还有几个例子here。
我不小心推送了一些大文件的提交,然后将其还原。但这会导致任何拉动此分支的人都在历史记录中获取这些文件,因此我决定删除或压缩这两个提交。但是,合并了一些分支。我不知道如何"git rebase -i"保持分支结构。
历史现在看起来像:
H - new commits
|
G - merge
| \
| F - commits on another branch
| |
E | - some other commits
| |
D | - corrected B
| |
C | - revert B
| |
B | - huge files
| /
A - early commit
可以改成关注吗?
h - new commits
|
g - merge
| \
| F - commits on another branch
| |
e | - some other commits
| |
d | - corrected B
| /
A - early commit
不,你不能。
每个提交的哈希值不仅包括索引中所有文件的哈希值,还包括提交的 parents.
的哈希值"Corrected B" 将会有一个与现在不同的 parent。那会改变散列。
可以修复此问题,但无法避免 force-pushing 修复,并在完成后让每个人 force-pull 它。
解决此问题的唯一真正方法是以下过程:
git checkout A
在分支分支之前检查 parent 提交。然后,创建两个工作分支:
git checkout -b corrected-mainline
git checkout -b corrected-fork
您现在位于 corrected-fork 分支。现在,在这个分支上,您应该能够 git cherry-pick
直到 F
提交的所有提交,跳过带有大文件的提交及其还原。如果这些提交中的任何一个是合并,则执行相同的合并。
现在,在 corrected-mainline
分支上做同样的事情
git checkout corrected-mainline
现在,git cherry-pick
主线分支上的所有提交,直到 G
合并之前的最后一次提交。然后,与 corrected-fork
分支合并。现在这是您更正的 G
合并提交。
完成 cherry-picking 图表中最初位于 G
之上的所有提交,以原始分支上的最后一次提交结束。
此时,你的工作分支的内容应该和你原来的分支的内容是一样的。验证是这样。
然后,删除您原来的分支,将您的工作分支重命名为它的名称。或者,使用 git reset --hard
将您的原始分支重置为更正后的工作分支。
然后执行 git push --force
,将您更正的分支向上推。当然,任何拉动分支的人最终都会得到 force-pull.
是的你可以但你不应该。
会要求你重写历史,替换掉服务器上已经推送的历史(需要强行推送,经常会被大家骂).
但如果您真的想要,那么 git filter-branch
就是您想要使用的,就像 this SO answer 中一样。所以你会做这样的事情:
git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = "<your commit to remove here>" ]
then
skip_commit "$@";
else
git commit-tree "$@";
fi' HEAD
还有几个例子here。