避免被cherry-pick-ing 删除:
是的,你可以很简单地做到这一点:你必须避免合并那些删除文件的提交。因此,当然,您最好不要进行会导致更改和删除文件的提交。
例子:
创建一个带有master 分支的git repo,该分支有两个文件:
~$ 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 并提交。以与master 冲突的方式修改foo 并提交:
~/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 上被修改,只有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
哎呀!在撤消bar 更改后,我忘记了git reset --hard。拿两个:
~/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 在那里:
~/gittest$ cat foo
foo
foo2
~/gittest$ cat bar
bar