Git 在合并过程中忽略删除的文件夹?
Git ignore deleted folders during a merge?
开发人员一直在开发从 master
分支出来的某些功能分支 f1
。
由于repo的模块化不好(系统是模块化的,但生活在一个整体的repo中)等原因,开发者决定删除"a bunch of irrelevant stuff"(与他的功能无关的其他模块)在f1
支线。功能单元测试成功,但分支现在包含系统的整个其他模块的所有这些删除。
在忽略文件夹删除的情况下将 f1
合并回 master
的最简单、最轻松的方法是什么?假设在 f1
中修改的一些文件也在 master
.
的演变中被修改
附加要求
f1
分支的工作可能需要在合并后继续一段时间。我不太确定到目前为止提出的答案会如何影响它。
假设源历史的质量是重中之重,我建议重写 F1
的历史以排除删除。任何 "painless fix" 都会留下奇怪的删除和添加,这将使未来对项目演变的分析变得复杂。
(顺便说一句,删除 "parts of the project I'm not working on" 的做法在客观上是不正确的。请参阅 "sparse checkout" 以获得客观上不正确的潜在解决方案。)
拥有 F1
分支副本的开发人员越多,任何人基于 F1
分支所做的更改(如果有的话)越多,历史重写就越乏味是。但是,如果这是一个仅由一个开发人员处理的功能分支,并且没有将该功能的合并推送到源,那么它可能会相当简单。
如果F1
本身是线性的,一个变基就可以了。例如
x -- x -- x -- x <--(master)
\
A -- B -- C <--(F1)
因为 master..F1
(可从 F1
访问但无法从 master
访问的提交集;A
、B
和 C
在本例中)不包括任何合并,并且没有其他分支基于 master..F1
中的任何提交,这是变基的简单情况。
git rebase -i master f1
您将看到一个 "TODO" 列表,其中包含 F1
上的每个提交的条目。将第一个提交的命令从 pick
更改为 edit
。退出编辑器,变基开始。
在暂时接受 A
"as is" 后,rebase 会暂停并提示您。现在您需要放回已删除的文件。您可以使用类似 git show --name-status
的内容来识别已删除的文件,并使用 git checkout HEAD^ -- path/to/deleted/file/or/directory
来恢复已删除的内容。
恢复所有文件后,git commit --amend
。然后继续rebase。
还有其他方法也可以使用;这是最简单的情况之一。
rebase 后,如果 F1
曾经被推送过,那么你可能需要强制推送它。 git push -f
此时任何在本地存储库中拥有 F1
副本的人都需要恢复(请参阅 git rebase
文档中的 "recover from upstream rebase")。如果有人基于 F1
工作过,他们将不得不将其重新设置为新的 F1
.
您应该能够完成对新 F1
的合并,而不会出现删除问题。
我希望我的 git-fu 达到标准。
假设MERGE_SOURCE
是你要合并的分支,这里F1
,PRESERVED_PATHS
是需要恢复的路径列表:
# Find out the commit from which F1 forked
MERGE_SPLIT_POINT=`git merge-base HEAD ${MERGE_SOURCE}`
# Rewrite the branch's history to unstage all changes
# (including removals) of the preserved paths
git filter-branch \
--index-filter 'git reset ${MERGE_SPLIT_POINT} -- ${PRESERVED_PATHS}' \
-- ${MERGE_SPLIT_POINT}..${MERGE_SOURCE}
# Regular merge with the resulting new branch
git merge ${MERGE_SOURCE}
开发人员一直在开发从 master
分支出来的某些功能分支 f1
。
由于repo的模块化不好(系统是模块化的,但生活在一个整体的repo中)等原因,开发者决定删除"a bunch of irrelevant stuff"(与他的功能无关的其他模块)在f1
支线。功能单元测试成功,但分支现在包含系统的整个其他模块的所有这些删除。
在忽略文件夹删除的情况下将 f1
合并回 master
的最简单、最轻松的方法是什么?假设在 f1
中修改的一些文件也在 master
.
附加要求
f1
分支的工作可能需要在合并后继续一段时间。我不太确定到目前为止提出的答案会如何影响它。
假设源历史的质量是重中之重,我建议重写 F1
的历史以排除删除。任何 "painless fix" 都会留下奇怪的删除和添加,这将使未来对项目演变的分析变得复杂。
(顺便说一句,删除 "parts of the project I'm not working on" 的做法在客观上是不正确的。请参阅 "sparse checkout" 以获得客观上不正确的潜在解决方案。)
拥有 F1
分支副本的开发人员越多,任何人基于 F1
分支所做的更改(如果有的话)越多,历史重写就越乏味是。但是,如果这是一个仅由一个开发人员处理的功能分支,并且没有将该功能的合并推送到源,那么它可能会相当简单。
如果F1
本身是线性的,一个变基就可以了。例如
x -- x -- x -- x <--(master)
\
A -- B -- C <--(F1)
因为 master..F1
(可从 F1
访问但无法从 master
访问的提交集;A
、B
和 C
在本例中)不包括任何合并,并且没有其他分支基于 master..F1
中的任何提交,这是变基的简单情况。
git rebase -i master f1
您将看到一个 "TODO" 列表,其中包含 F1
上的每个提交的条目。将第一个提交的命令从 pick
更改为 edit
。退出编辑器,变基开始。
在暂时接受 A
"as is" 后,rebase 会暂停并提示您。现在您需要放回已删除的文件。您可以使用类似 git show --name-status
的内容来识别已删除的文件,并使用 git checkout HEAD^ -- path/to/deleted/file/or/directory
来恢复已删除的内容。
恢复所有文件后,git commit --amend
。然后继续rebase。
还有其他方法也可以使用;这是最简单的情况之一。
rebase 后,如果 F1
曾经被推送过,那么你可能需要强制推送它。 git push -f
此时任何在本地存储库中拥有 F1
副本的人都需要恢复(请参阅 git rebase
文档中的 "recover from upstream rebase")。如果有人基于 F1
工作过,他们将不得不将其重新设置为新的 F1
.
您应该能够完成对新 F1
的合并,而不会出现删除问题。
我希望我的 git-fu 达到标准。
假设MERGE_SOURCE
是你要合并的分支,这里F1
,PRESERVED_PATHS
是需要恢复的路径列表:
# Find out the commit from which F1 forked
MERGE_SPLIT_POINT=`git merge-base HEAD ${MERGE_SOURCE}`
# Rewrite the branch's history to unstage all changes
# (including removals) of the preserved paths
git filter-branch \
--index-filter 'git reset ${MERGE_SPLIT_POINT} -- ${PRESERVED_PATHS}' \
-- ${MERGE_SPLIT_POINT}..${MERGE_SOURCE}
# Regular merge with the resulting new branch
git merge ${MERGE_SOURCE}