まず、マージによってコードが削除される状況を再現してみましょう。
例は次のとおりです。
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. 開発ブランチをマージします。
$ 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 がマージに失敗しただけでなく、ファイルも削除したことがわかりました。なぜですか?
まず明確にしておきますが、git のマージは数学的なコレクションのマージですか?
いいえ。数学における併合とは、集合 A に {a, b} があり、集合 B に {c} があり、併合された集合は {a, b, c} になります。
git のマージに関しては、ソースコードファイルのマージではなく、ブランチ開発者の希望をマージするものだと思います。これを理解すると、git がマージ時にファイルを削除する理由を理解しやすくなります。
私の実験では、master ブランチを会社の創設者に喩えると、彼は最初にファイル master.txt を作成し、それを会社の倉庫に置き、それを自分で使用しました。その後、マスターは隠遁して練習したいと考えたので、プロジェクトマネージャーの開発を見つけ、会社のオリジナルファイルに基づいてファイルdevelve.txtを作成し、それをCCP自身が使用するために会社の倉庫に置きました。しばらくして、開発者もリトリートで練習したいと考えたので、別のプロジェクト マネージャーである feature1 を見つけ、彼は自分用にファイル feature1.txt を作成しました。
マスターは隠遁中のため、会社の倉庫にファイルdevelop.txtとfeature1.txtがあることを知りません。マスターと開発がマージすると、両者はウェアハウス内のファイルを使用する意思を交換します。マージの結果、マスターはウェアハウスにdevelop.txtファイルがあることを認識し、それを使用できるようになります。マージはマスターがdevelop.txtファイルをコピーすることを意味するのではなく、使用できるdevelop.txtファイルのコピーがウェアハウスに存在することを意味することに注意してください。
同様に、マスターが feature1 とマージすると、マスターはウェアハウスに使用できるファイル feature1.txt があることを認識します。
創業者が出てきて、プロジェクトマネージャーのお二人と意見交換をしたような感じです。会社の創設者たちは、会社の資産が増加していることに気づきました。3つのファイルになりました。
次に、master と feature1 の両方が会社を管理します。マスターはファイル master.txt、develop.txt を削除しました。feature1 はファイル feature1.txt を削除しました。
ここで git の削除について理解する必要があることに注意してください。ファイルをウェアハウスに送信する限り、ファイルは常にウェアハウス内にあります。必要な限り、いつでも見つけることができます。したがって、ファイルの削除は、ウェアハウスからの実際の削除ではなく、ブランチによるファイルの非推奨として理解できます。
このときの状況は、マスターはウェアハウス内のfeature1.txtファイルのみを使用し、master.txtとdevelop.txtは破棄しています。feature1 は master.txt ファイルとdevelopment.txt ファイルのみを使用し、feature1.txt ファイルは破棄されます。マスターが feature1 ブランチをマージする場合、多くの人はファイルのマージだと考えますが、マスター ブランチにはファイル master.txt とdevelopment.txt がありません。次に、master.txt とdevelopment.txt を feature1 にマージします。このように、master ブランチには 3 つのファイルがあります。実際にはそうではなく、この合併は基本的にマスターが機能 1 を採用する意図を持っています。マスターが master.txt ファイルとdevelopment.txt ファイルを削除したとき、feature1 は何の異議も表明しなかったため、git は競合がないとみなしたため、マスターの希望は master.txt ファイルとdevelopment.txt ファイルを破棄することでした。マージ時のマスターになります。さらに、feature1 は feature1.txt ファイルを非推奨にしており、master は異議を唱えていないため、git は競合がないと判断し、feature1 の希望を採用し、マージ中に master ブランチ内の feature1.txt ファイルを削除します。合併の最終結果は、2 つのブランチのファイルを使用する最新の意欲が結合されることです。つまり、合併後、master ブランチにはファイルが存在しません。
ブランチをマージするときにソースコードを git delete する人が多いですが、これが原則です。一度理解すれば、ソースコードが削除される可能性を回避する方法はたくさんあります。