先再现一下合并会删除代码的情况:

示例如下:

1、初始化一个仓库,并新建一个master.txt文件,然后提交。

$ git init tem

Initialized empty Git repository in D:/temp/tem/.git/

$ cd tem

$ touch master.txt

$ vim master.txt

$ cat master.txt

this is master branch!

$ git commit -a -m "commit master branch"

[master (root-commit) 3e4d6ff] commit master branch

1 file changed, 1 insertion(+)

create mode 100644 master.txt

2、新建一个分支develop,创建一个文件develop.txt,并提交。

$ git checkout -b develop

Switched to a new branch 'develop'

$ touch develop.txt

$ vim develop.txt

$ cat develop.txt

this is develop branch!

$ git add .

$ git commit -a -m "commit develop branch"

[develop f439ba3] commit develop branch

1 file changed, 1 insertion(+)

create mode 100644 develop.txt

3、创建分支feature1,新建文件feature.txt,并提交。

$ git checkout -b feature1

Switched to a new branch 'feature1'

$ touch feature1.txt

$ vim feature1.txt

$ git add .

$ git commit -a -m "feature1 commite"

[feature1 98e05e7] feature1 commite

1 file changed, 1 insertion(+)

create mode 100644 feature1.txt

4、合并develop分支。

$ git checkout master

Switched to branch 'master'

$ ll

total 1

-rw-r--r-- 1 mydwh 197121 23 Jul 22 16:18 master.txt

$ git merge develop

Updating 3e4d6ff..f439ba3

Fast-forward

develop.txt | 1 +

1 file changed, 1 insertion(+)

create mode 100644 develop.txt

5、合并feature1分支

$ git merge feature1

Updating f439ba3..98e05e7

Fast-forward

feature1.txt | 1 +

1 file changed, 1 insertion(+)

create mode 100644 feature1.txt

$ ll

total 3

-rw-r--r-- 1 mydwh 197121 25 Jul 22 17:01 develop.txt

-rw-r--r-- 1 mydwh 197121 25 Jul 22 17:03 feature1.txt

-rw-r--r-- 1 mydwh 197121 23 Jul 22 16:18 master.txt

6、删除feature1.txt文件并提交。

$ rm feature1.txt

$ ll

total 2

-rw-r--r-- 1 mydwh 197121 25 Jul 22 17:01 develop.txt

-rw-r--r-- 1 mydwh 197121 23 Jul 22 16:18 master.txt

$ git commit -a -m "delete feature1.txt,commit master branch"

[master 88cd117] delete feature1.txt,commit master branch

1 file changed, 1 deletion(-)

delete mode 100644 feature1.txt

7、登出到feature1分支,并删除master.txt,develop.txt,然后提交。

$ git checkout feature1

Switched to branch 'feature1'

$ ll

total 3

-rw-r--r-- 1 mydwh 197121 25 Jul 22 17:01 develop.txt

-rw-r--r-- 1 mydwh 197121 25 Jul 22 17:08 feature1.txt

-rw-r--r-- 1 mydwh 197121 23 Jul 22 16:18 master.txt

$ rm master.txt develop.txt

$ ll

total 1

-rw-r--r-- 1 mydwh 197121 25 Jul 22 17:08 feature1.txt

$ git commit -a -m "delete master.txt ,develop.txt,commit feature1 branch"

[feature1 70b4ed7] delete master.txt ,develop.txt,commit feature1 branch

2 files changed, 2 deletions(-)

delete mode 100644 develop.txt

delete mode 100644 master.txt

8、登出master分支,合并feature1分支。

$ git checkout master

Switched to branch 'master'

$ ll

total 2

-rw-r--r-- 1 mydwh 197121 25 Jul 22 17:11 develop.txt

-rw-r--r-- 1 mydwh 197121 24 Jul 22 17:11 master.txt

$ git merge feature1

Merge made by the 'ort' strategy.

develop.txt | 1 -

master.txt | 1 -

2 files changed, 2 deletions(-)

delete mode 100644 develop.txt

delete mode 100644 master.txt

$ ll

total 0

问题:最后一次合并,发现git不但没有合并,反而将文件给删除了,why?

首先澄清一下,git的合并是数学的集合合并吗?

非也。数学中的合并是A集合有{a,b},B集合有{c},那么合并后的集合就是{a,b,c}。

而git的合并,我认为是分支开发者意愿的合并,而不是源代码文件的合并。理解这点,对git为什么在合并时会删除文件就好理解了。

在我的实验中,如果把master分支比作公司创始人,他最先创建了文件master.txt,放到公司的仓库中,自己使用。然后master想去闭关修行,就找了一个项目经理develop,他在公司原有的基础上创建了文件develop.txt,并放到公司仓库中共自己使用。一段时间后,develop也想闭关修行,就又找了一个项目经理feature1,他创建了文件feature1.txt,供自己使用。

由于master闭关,他是不知道公司仓库里有文件develop.txt和feature1.txt的。当master与develop合并时,是他们两人共同交换了对仓库中文件的使用意愿。合并的结果,那就是master感知到仓库中有develop.txt文件,自己可以使用。注意,合并并不是master复制了develop.txt文件,而是知道仓库中有一份develop.txt文件,我可以使用。

同理,当master与feature1合并时,master感知到仓库有一份文件feature1.txt文件,自己可以使用。

这就好比,公司创始人出山了,分别与两位项目经理交换了一下意见。公司创始人发现公司资产增多了。变成了三个文件。

接下来,master与feature1都对公司进行治理。master删除了文件master.txt,develop.txt。feature1删除了文件feature1.txt。

注意这儿要理解git的删除,只要你把文件提交到仓库里,那就永远在仓库里,只要你想要,总能找到。因此,对文件的删除,可以理解为分支对文件的弃用,而不是真的从仓库中删除了。

此时的局面就是,master只使用仓库中的feature1.txt文件,而弃用master.txt,develop.txt。而feature1只使用master.txt,develop.txt文件,而弃用feature1.txt文件。当master要合并feature1分支时,很多人以为是文件的合并,那么master分支中没有文件master.txt,develop.txt,那就把feature1分支中的master.txt,develop.txt合并过来,这样,master分支就有三个文件了。而实质上不是这样子的,合并实质上是master采纳feature1的意愿。因为master删除master.txt,develop.txt文件时,feature1没有表示异议,那git就认为没冲突,master的意愿就是弃用master.txt,develop.txt这两个文件,git在合并时尊重了master的意愿。又feature1对feature1.txt文件是弃用的,master没有表示异议,那git就认为没冲突,采纳了feature1的意愿,在合并时就删除了master分支中的feature1.txt文件。最后合并的结果是:综合了两个分支对文件最新的使用意愿,那就是合并后,master分支中没有文件了。

很多人在合并分支时出现git删除源代码的情况,原理就是这样的。当你理解后,就有很多办法避免出现源代码被删除的可能。

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: