我可以在合并到另一个分支时从git分支中删除单个文件而不删除它们吗?

时间:2014-04-05 13:17:08

标签: git merge branch

我正处于一个项目的中间,那里有两个主要的开发分支,因为项目由一个库和一个库的实现组成,这两个分支都在不同的分支中并行开发。

我的工作流程是,一旦将足够的功能添加到库中,我将库分支与--no-ff合并到实现(名为core)分支中,理想情况下,库分支应该永远不会看到来自实现,因为否则两个分支都将对相同的实现文件进行更改。不幸的是,情况并非如此,因为我从一个现有的源文件夹启动了该项目,该文件夹中有一些来自库的文件和部分启动的实现,我忘了在最初从master分割两个工作分支时删除实现文件。

工作流:

$ git checkout library

..做出一些改变..

$ git commit -am "updated library"
$ git checkout core
$ git merge --no-ff library

此时我通常必须处理库更新导致的冲突,这些冲突更改library分支中的实现文件,同时合并core分支的更改,并更新相同的文件即使core分支已对这些文件进行了自己的更新。

如果将library分支中的实现目录合并到实现分支中,如何在不删除它们的情况下删除它们?

3 个答案:

答案 0 :(得分:2)

  

当我将实现目录合并到实现分支中时,如何从库分支中删除实现目录而不删除它们?

您可以使用--no-commit执行合并,恢复已删除的文件并完成提交。

请参阅“git merge: Removing files I want to keep!”作为具体示例。

git checkout dev1
git merge --no-commit dev2
git checkout dev1 implementationFile
git add implementationFile
git commit

答案 1 :(得分:1)

你似乎对此有点不对 - 你不应该为此目的使用分支;相反,您应该使用2个单独的存储库,一个库和一个实现/客户端。然后,客户端将具有库repo,例如,它的子模块(虽然还有其他方法)。

这样,这两个回购之间的文件就不会有任何重叠,这就是你想要的,根据你的要求决定。

为了转换当前以2个分支形式的内容,您将使用git filter-branch从属于分支B的分支A文件中过滤掉,反之亦然,因此您最终会得到2个repos只有库或客户端的文件(实现)。这当然具有修改历史记录的缺点,因此如果您想避免这种情况,您只需使用普通git rmgit commit进行删除。

答案 2 :(得分:0)

避免cherry-pick围绕它删除:

是的,您可以非常简单地执行此操作:必须避免合并删除文件的提交。所以,当然,你不应该做出改变删除文件的提交。

示例:

创建一个带有master分支的git仓库,该分支有两个文件:

~$ mkdir gittest
~$ cd gittest
~/gittest$ git init
Initialized empty Git repository in /home/kaz/gittest/.git/
~/gittest$ echo foo > foo
~/gittest$ echo bar > bar
~/gittest$ git add foo bar
~/gittest$ git commit -m "root commit"
[master (root-commit) 1c1860f] root commit
 2 files changed, 2 insertions(+)
 create mode 100644 bar
 create mode 100644 foo

从根提交中拍摄topic分支:

~/gittest$ git branch topic

在两个文件的master上创建第二个版本:

~/gittest$ echo foo >> foo
~/gittest$ echo bar >> bar
~/gittest$ git diff
diff --git a/bar b/bar
index 5716ca5..a486f1a 100644
--- a/bar
+++ b/bar
@@ -1 +1,2 @@
 bar
+bar
diff --git a/foo b/foo
index 257cc56..0d55bed 100644
--- a/foo
+++ b/foo
@@ -1 +1,2 @@
 foo
+foo
~/gittest$ git commit -a -m "hack 1"
[master ded65d8] hack 1
 2 files changed, 2 insertions(+)

切换到topic。删除bar并提交。与foo冲突地修改master并提交:

~/gittest$ git checkout topic
Switched to branch 'topic'
~/gittest$ git rm bar
rm 'bar'
~/gittest$ git commit -m "delete bar"
[topic 8a4009d] delete bar
 1 file changed, 1 deletion(-)
 delete mode 100644 bar
~/gittest$ echo "foo2" > foo
~/gittest$ git commit -a -m "replace foo"
[topic abfa329] replace foo
 1 file changed, 1 insertion(+), 1 deletion(-)

回顾topic上的历史记录:

~/gittest$ git log --oneline
abfa329 replace foo
8a4009d delete bar
1c1860f root commit

返回master

~/gittest$ git checkout master
Switched to branch 'master'
~/gittest$ git log --oneline
ded65d8 hack 1
1c1860f root commit

现在从主题中挑选abfa329 replace foo,避免使用8a4009d delete bar

$ git cherry-pick abfa329
error: could not apply abfa329... replace foo
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

修复foo上的冲突并提交:

~/gittest$ cat foo
<<<<<<< HEAD
foo
foo
=======
foo2
>>>>>>> abfa329... replace foo
~/gittest$ cat > foo
foo
foo2
~/gittest$ git add foo
~/gittest$ git commit -m "merged topic, avoiding deletion"
[master 320818f] merged topic, avoiding deletion
 1 file changed, 1 insertion(+), 1 deletion(-)

请注意,bar仍然存在:

~/gittest$ ls bar
bar
~/gittest$ cat bar
bar
bar

在合并期间或之后使用git reset撤消不需要的删除:

如果您确实选择了不需要的删除,则可以轻松撤消。

让我们将示例master分支回滚到hack 1提交并重写,以便在bar上不修改master,仅{{1} }}:

foo

现在,让我们合并~/gittest$ git reset --hard ded65d8 HEAD is now at ded65d8 hack 1 ~/gittest$ git reset HEAD^ -- bar Unstaged changes after reset: M bar ~/gittest$ git commit --amend -m "hack1: bar only" [master 623908a] hack1: bar only 1 file changed, 1 insertion(+) ~/gittest$ git log --oneline 623908a hack1: bar only 1c1860f root commit ~/gittest$ git show -p commit 623908a3bf6b2fb81b0bf8309fa2e83cd602986a Author: Kaz <kaz@stackexchange.example.com> Date: Sat Dec 20 08:03:27 2014 -0800 hack1: bar only diff --git a/foo b/foo index 257cc56..0d55bed 100644 --- a/foo +++ b/foo @@ -1 +1,2 @@ foo +foo ,而不怀疑有不想要的删除:

topic

糟糕!撤消~/gittest$ git merge topic error: Your local changes to the following files would be overwritten by merge: bar Please, commit your changes or stash them before you can merge. Aborting 更改后,我忘记了git reset --hard。拿两个:

bar

好的,合并会自动删除~/gittest$ git reset --hard HEAD is now at 623908a hack1: bar only ~/gittest$ git merge topic Auto-merging foo CONFLICT (content): Merge conflict in foo Removing bar Automatic merge failed; fix conflicts and then commit the result. (因为bar上没有修改bar因此没有冲突)。 master上存在冲突,与foo案件完全相同,所以让我们先解决这个问题:

cherry-pick

现在,回滚删除~/gittest$ cat > foo foo foo2 ~/gittest$ git add foo 。请注意,bar不在工作树中,现在仍然保持这种状态:

bar

我们承诺一切:

~/gittest$ git reset HEAD^ -- bar
Unstaged changes after reset:
D   bar

现在我们带回~/gittest$ git commit -m "merged topic, except deletion of bar" [master 57b7fca] merged topic, except deletion of bar

bar

糟糕,我的意思是~/gittest$ git reset Unstaged changes after reset: D bar

--hard

使用~/gittest$ git reset --hard HEAD is now at 57b7fca merged topic, except deletion of bar

查看日志
--graph

验证文件内容。合并了~/gittest$ git log --graph --oneline * 57b7fca merged topic, except deletion of bar |\ | * abfa329 replace foo | * 8a4009d delete bar * | 623908a hack1: bar only |/ * 1c1860f root commit foo就在那里:

bar