[Git] 動作を試す 実行例58：format-patchで作業内容をpatchテキストファイルにまとめて別送付する

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/1a3300da8886c17d5405) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/16bc7015ecc4f1040a06) |
|:-:|:-:|:-:|

# 変更を別で送付する方法: 3種類

・format-patchを使用
・bundleを使用
・diffを使用 (非推奨)

参考: 

※Pro Git本
Git - プロジェクトへの貢献
https://git-scm.com/book/ja/v2/Git-%E3%81%A7%E3%81%AE%E5%88%86%E6%95%A3%E4%BD%9C%E6%A5%AD-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%B8%E3%81%AE%E8%B2%A2%E7%8C%AE#r_project_over_email

Git - プロジェクトの運営
https://git-scm.com/book/ja/v2/Git-%E3%81%A7%E3%81%AE%E5%88%86%E6%95%A3%E4%BD%9C%E6%A5%AD-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E9%81%8B%E5%96%B6

# 実行例

メールでパッチをやり取りする - Qiita
https://qiita.com/troter/items/3b4cd6972c338b95835d#git%E3%81%AE%E5%A0%B4%E5%90%88

Git - メール
https://git-scm.com/book/ja/v2/%E4%BB%98%E9%8C%B2-C%3A-Git%E3%81%AE%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89-%E3%83%A1%E3%83%BC%E3%83%AB

```
(※準備: local-repo2の変更内容を適当に作成)

cd /test-space/local-repo2
git log --oneline --graph --all
↓
結果: 
* e009b2d (origin/branch-R1) message R2
| * c69a305 (HEAD -> master, origin/master) message R1
| * 94996a0 message4
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

git checkout branch-R1

echo Sample-Added-S1 >> test1.txt
git commit -a -m "message S1"

echo Sample-Added-S2 >> test1.txt
git commit -a -m "message S2"

git log --oneline --graph --all
↓
結果: 
* 09f2860 (HEAD -> branch-R1) message S2
* 6bbd0ed message S1
* e009b2d (origin/branch-R1) message R2
| * c69a305 (origin/master, master) message R1
| * 94996a0 message4
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

(※マージの変更も作成)
git merge master
↓
結果: 
Auto-merging test1.txt
CONFLICT (content): Merge conflict in test1.txt
Automatic merge failed; fix conflicts and then commit the result.

git diff
↓
結果: 
diff --cc test1.txt
index 634f4c9,de6fe38..0000000
--- a/test1.txt
+++ b/test1.txt
@@@ -1,6 -1,5 +1,11 @@@
  Sample-Added-11
  Sample-Added-12
  Sample-Added-13
++<<<<<<< HEAD
 +Sample-Added-R2
 +Sample-Added-S1
 +Sample-Added-S2
++=======
+ Sample-Added-14
+ Sample-Added-R1
++>>>>>>> master

(※コンフリクトを手動で解消)
echo Sample-Added-11 > test1.txt
echo Sample-Added-12 >> test1.txt
echo Sample-Added-13 >> test1.txt
echo Sample-Added-14 >> test1.txt
echo Sample-Added-R1 >> test1.txt
echo Sample-Added-R2 >> test1.txt
echo Sample-Added-S1 >> test1.txt
echo Sample-Added-S2 >> test1.txt
type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14
Sample-Added-R1
Sample-Added-R2
Sample-Added-S1
Sample-Added-S2

git add .
git status -s
↓
結果: 
M  test1.txt
A  test4.txt

※マージ処置をコミット
git commit --no-edit
↓
結果: 
[branch-R1 ed2b786] Merge branch 'master' into branch-R1

git log --oneline --graph --all
↓
結果: 
*   ed2b786 (HEAD -> branch-R1) Merge branch 'master' into branch-R1
|\
| * c69a305 (origin/master, master) message R1
| * 94996a0 message4
* | 09f2860 message S2
* | 6bbd0ed message S1
* | e009b2d (origin/branch-R1) message R2
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

echo Sample-Added-S3 >> test1.txt
git commit -a -m "message S3"

git log --oneline --graph --all
↓
結果: 
* d67f7ab (HEAD -> branch-R1) message S3
*   ed2b786 Merge branch 'master' into branch-R1
|\
| * c69a305 (origin/master, master) message R1
| * 94996a0 message4
* | 09f2860 message S2
* | 6bbd0ed message S1
* | e009b2d (origin/branch-R1) message R2
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

-----

(※試行用にlocal-repo3を作成)

cd /test-space
mkdir local-repo3
cd /test-space/local-repo3

git init
git remote add origin "D:/test-space/remote-repo1.git"

git fetch origin

git log --oneline --graph --all
↓
結果: 
* 1247fa9 (origin/master) message R4
* fab68d8 (origin/branch-R2) message R3
* c69a305 message R1
* 94996a0 message4
| * e009b2d (origin/branch-R1) message R2
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

-----

(※local-repo2の変更内容1つを、local-repo3へ送付して反映)

cd /test-space/local-repo2

※作業内容をpatchテキストファイルにまとめる
git format-patch e009b2d
↓
結果: 
0001-message4.patch
0002-message-R1.patch
0003-message-S1.patch
0004-message-S2.patch
0005-message-S3.patch

dir /b
↓
結果: 
0001-message4.patch
0002-message-R1.patch
0003-message-S1.patch
0004-message-S2.patch
0005-message-S3.patch
test1.txt
test2.txt
test4.txt

(※e009b2dを含まずに、それより新しいコミット履歴の全てを、コミット毎にパッチファイルが、カレントパス直下に作成される)

(※一旦削除)
del *.patch

dir /b
↓
結果: 
test1.txt
test2.txt
test4.txt

※作業内容をpatchテキストファイルにまとめる (1つのコミット履歴だけ)
git format-patch e009b2d..6bbd0ed
↓
結果: 
0001-message-S1.patch

type 0001-message-S1.patch
↓
結果: 
From 6bbd0ed49e37456cf3c85d2eee32f4639413839f Mon Sep 17 00:00:00 2001
From: person1 <person1@abc.def>
Date: Sun Jan 1 20:10:00 2023 +0900
Subject: [PATCH] message S1

---
 test1.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test1.txt b/test1.txt
index f4e41fe..2374ac8 100644
--- a/test1.txt
+++ b/test1.txt
@@ -2,3 +2,4 @@ Sample-Added-11
 Sample-Added-12
 Sample-Added-13
 Sample-Added-R2
+Sample-Added-S1
--
2.40.0.windows.1

(※「Sample-Added-S1」1行の追加分だけになっている、OK)

-----

(※local-repo3でpatchテキストファイルを反映)

xcopy "D:\test-space\local-repo2\0001-message-S1.patch" "D:\test-space\local-repo3\0001-message-S1.patch"
cd /test-space/local-repo3
git checkout branch-R1

※patchテキストファイルを適用
git am 0001-message-S1.patch
↓
結果: 
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S1
warning: 1 line adds whitespace errors.
Applying: message S1

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-R2
Sample-Added-S1

git log --oneline --graph --all
↓
結果: 
* bdf6e26 (HEAD -> branch-R1) message S1
* e009b2d (origin/branch-R1) message R2
| * 1247fa9 (origin/master) message R4
| * fab68d8 (origin/branch-R2) message R3
| * c69a305 message R1
| * 94996a0 message4
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

(※「message S1」がコミット履歴に追加されている、OK)

-----

(※誤った適用: 再度適用してみると)
git am 0001-message-S1.patch
↓
結果: 
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S1
error: patch failed: test1.txt:2
error: test1.txt: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Applying: message S1
Patch failed at 0001 message S1
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

(※エラーが発生、変更分は未適用、「am session」の状態で停止となる)

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-R2
Sample-Added-S1

※適用に失敗したパッチ内容を見る
git am --show-current-patch=diff
↓
結果: 
---
 test1.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test1.txt b/test1.txt
index f4e41fe..2374ac8 100644
--- a/test1.txt
+++ b/test1.txt
@@ -2,3 +2,4 @@ Sample-Added-11
 Sample-Added-12
 Sample-Added-13
 Sample-Added-R2
+Sample-Added-S1
--
2.40.0.windows.1

git am --abort
↓
結果: 
(なし)

(※誤った適用: 異なるブランチで適用してみると)
git checkout master
git am 0001-message-S1.patch
↓
結果: 
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S1
error: patch failed: test1.txt:2
error: test1.txt: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Applying: message S1
Patch failed at 0001 message S1
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

(※エラーが発生、変更分は未適用、「am session」中の状態で停止となる)

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14
Sample-Added-R1
Sample-Added-R3
Sample-Added-R4

git am --abort
↓
結果: 
(なし)

git checkout branch-R1

-----

(※.patch内の変更分とは離れた行で別の変更が既にある場合の、適用動作を見ると)

(※「message S1」のコミットを戻す)
git reset --hard e009b2d
git log --oneline --graph --all
↓
結果: 
* 1247fa9 (origin/master, master) message R4
* fab68d8 (origin/branch-R2) message R3
* c69a305 message R1
* 94996a0 message4
| * e009b2d (HEAD -> branch-R1, origin/branch-R1) message R2
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

(※.patch内の変更分とは離れた行で別の変更を加える)

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-R2

echo Sample-Added-11 > test1.txt
echo Sample-Added-**-MOD >> test1.txt
echo Sample-Added-**-MOD >> test1.txt
echo Sample-Added-12 >> test1.txt
echo Sample-Added-13 >> test1.txt
echo Sample-Added-R2 >> test1.txt
type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-**-MOD
Sample-Added-**-MOD
Sample-Added-12
Sample-Added-13
Sample-Added-R2

(※local-repo3で反映)

※patchテキストファイルを適用
git am 0001-message-S1.patch
↓
結果: 
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S1
error: test1.txt: does not match index
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Applying: message S1
Patch failed at 0001 message S1
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-**-MOD
Sample-Added-**-MOD
Sample-Added-12
Sample-Added-13
Sample-Added-R2

(※行番目に変化がある変更の場合はエラーが発生、適用不可)

git am --abort
↓
結果: 
(なし)

-----

(※.patch内の変更分とは離れた行で別の変更を加える: ケース2)

echo Sample-Added-11-MOD > test1.txt
echo Sample-Added-12 >> test1.txt
echo Sample-Added-13 >> test1.txt
echo Sample-Added-R2 >> test1.txt
type test1.txt
↓
結果: 
Sample-Added-11-MOD
Sample-Added-12
Sample-Added-13
Sample-Added-R2

(※local-repo3で反映)

※patchテキストファイルを適用
git am 0001-message-S1.patch
↓
結果: 
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S1
error: test1.txt: does not match index
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Applying: message S1
Patch failed at 0001 message S1
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

type test1.txt
↓
結果: 
Sample-Added-11-MOD
Sample-Added-12
Sample-Added-13
Sample-Added-R2

(※いかなる変更がある場合もエラーが発生、適用不可。
　インデックス(index f4e41fe..2374ac8)の一致を調べる模様)

git am --abort
↓
結果: 
(なし)

-----

(※.patch内の変更分とは離れた行で別の変更を加える: ケース3)

echo Sample-Added-1* > test1.txt
echo Sample-Added-12 >> test1.txt
echo Sample-Added-13 >> test1.txt
echo Sample-Added-R2 >> test1.txt
type test1.txt
↓
結果: 
Sample-Added-11-MOD
Sample-Added-12
Sample-Added-13
Sample-Added-R2

(※local-repo3で反映)

※patchテキストファイルを適用
git am 0001-message-S1.patch
↓
結果: 
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S1
error: test1.txt: does not match index
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Applying: message S1
Patch failed at 0001 message S1
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

type test1.txt
↓
結果: 
Sample-Added-1*
Sample-Added-12
Sample-Added-13
Sample-Added-R2

(※いかなる変更がある場合もエラーが発生、適用不可。
　インデックス(index f4e41fe..2374ac8)の一致を調べる模様)

git am --abort
↓
結果: 
(なし)

-----

(※元に戻す)
git reset --hard e009b2d

※patchテキストファイルを適用
git am 0001-message-S1.patch
↓
結果: 
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S1
warning: 1 line adds whitespace errors.
Applying: message S1

(※削除)
del *.patch

-----

(※local-repo2のマージ入り・複数の変更内容を、local-repo3へ送付して反映)

cd /test-space/local-repo2

(※始めに削除)
del *.patch

※複数の作業内容をpatchテキストファイルにまとめる
git format-patch e009b2d..ed2b786
↓
結果: 
0001-message4.patch
0002-message-R1.patch
0003-message-S1.patch
0004-message-S2.patch

(※削除)
del *.patch

※複数の作業内容をpatchテキストファイルにまとめる
git format-patch e009b2d..d67f7ab
↓
結果: 
0001-message4.patch
0002-message-R1.patch
0003-message-S1.patch
0004-message-S2.patch
0005-message-S3.patch

(※マージのコミット履歴が含まれない模様)
(※コミット時刻の順に全てのコミットに対して.patchが生成され、指定のブランチのみに絞ったものにはならない模様)

type 0005-message-S3.patch
↓
結果: 
From d67f7ab821fc6d37a369d42d5ec8568fe89d5ab4 Mon Sep 17 00:00:00 2001
From: person1 <person1@abc.def>
Date: Sun Jan 1 20:20:00 2023 +0900
Subject: [PATCH 5/5] message S3

---
 test1.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test1.txt b/test1.txt
index 61da64e..7936a9a 100644
--- a/test1.txt
+++ b/test1.txt
@@ -6,3 +6,4 @@ Sample-Added-R1
 Sample-Added-R2
 Sample-Added-S1
 Sample-Added-S2
+Sample-Added-S3
--
2.40.0.windows.1

(※マージのコミット履歴は、format-patchでは含められない模様)
```

参考: マージのコミット履歴は、format-patchでは含められない

Git - git-format-patch Documentation
https://git-scm.com/docs/git-format-patch
↓
引用: 
Prepare each non-merge commit with its "patch" in one "message" per commit, 

docs/format-patch: mention handling of merges · git/git@8e0601f · GitHub
https://github.com/git/git/commit/8e0601f568ebf512f2edc606bdbf1a508b3c28a6
↓
引用: 
docs/format-patch: mention handling of merges
Format-patch doesn't have a way to format merges in a way that can be
applied by git-am (or any other tool), and so it just omits them.

```
(※local-repo3でpatchテキストファイルを反映)

xcopy "D:\test-space\local-repo2\*.patch" "D:\test-space\local-repo3\"
↓
結果: 
D:\test-space\local-repo2\0001-message4.patch
D:\test-space\local-repo2\0002-message-R1.patch
D:\test-space\local-repo2\0003-message-S1.patch
D:\test-space\local-repo2\0004-message-S2.patch
D:\test-space\local-repo2\0005-message-S3.patch
5 個のファイルをコピーしました

cd /test-space/local-repo3

git checkout branch-R1
git log --oneline --graph --all
↓
結果: 
* bdf6e26 (HEAD -> branch-R1) message S1
* e009b2d (origin/branch-R1) message R2
| * 1247fa9 (origin/master, master) message R4
| * fab68d8 (origin/branch-R2) message R3
| * c69a305 message R1
| * 94996a0 message4
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

※複数のpatchテキストファイルを適用
git am 0001-message4.patch 0002-message-R1.patch 0003-message-S1.patch 0004-message-S2.patch 0005-message-S3.patch
↓
結果: 
.git/rebase-apply/patch:15: trailing whitespace.
Sample-Added-14
.git/rebase-apply/patch:22: trailing whitespace.
Sample-Added-41
error: patch failed: test1.txt:1
error: test1.txt: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Applying: message4
Patch failed at 0001 message4
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

(※複数の適用時は、ファイル名を全て指定する方法しかない模様)

※適用に失敗したパッチ内容を見る
git am --show-current-patch=diff
---
 test1.txt | 1 +
 test4.txt | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 test4.txt

diff --git a/test1.txt b/test1.txt
index 2cb4452..bb7eb1a 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1,3 +1,4 @@
 Sample-Added-11
 Sample-Added-12
 Sample-Added-13
+Sample-Added-14
diff --git a/test4.txt b/test4.txt
new file mode 100644
index 0000000..d42c59e
--- /dev/null
+++ b/test4.txt
@@ -0,0 +1 @@
+Sample-Added-41
--
2.40.0.windows.1

git log --oneline --graph --all
↓
結果: 
* bdf6e26 (HEAD -> branch-R1) message S1
* e009b2d (origin/branch-R1) message R2
| * 1247fa9 (origin/master, master) message R4
| * fab68d8 (origin/branch-R2) message R3
| * c69a305 message R1
| * 94996a0 message4
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

(※amの適用失敗時は、全てが適用されない状態になる)

git am --abort

-----

(※適用する適切なパッチを手動で選択して反映)

※複数のpatchテキストファイルを適用
git am 0004-message-S2.patch 0005-message-S3.patch
↓
結果: 
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S2
warning: 1 line adds whitespace errors.
.git/rebase-apply/patch:13: trailing whitespace.
Sample-Added-S3
warning: 1 line adds whitespace errors.
Applying: message S2
Applying: message S3

git log --oneline --graph --all
↓
結果: 
* e6fd8a5 (HEAD -> branch-R1) message S3
* 42fc049 message S2
* bdf6e26 message S1
* e009b2d (origin/branch-R1) message R2
| * 1247fa9 (origin/master, master) message R4
| * fab68d8 (origin/branch-R2) message R3
| * c69a305 message R1
| * 94996a0 message4
|/
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

(※適用はOK、ただしマージの変更分は適用していない)

-----

cd /test-space/local-repo2

(※削除)
del *.patch

-----

(※local-repo3を削除)
cd /test-space
rd /s /q "/test-space/local-repo3"
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。