一覧SE-04-2 · Gitの共同作業

rebaseとcherry-pick

変更内容の同一性とコミットの同一性を分け、再適用後の親・ファイル構成・履歴を確認します。

説明

Gitでは、同じ変更を別の履歴の上へ適用できます。rebaseは一連のコミットを別の基点へ載せ直し、cherry-pickは指定したコミットの変更を現在のブランチへ適用します。変更内容が同じでも、親が変わればコミットIDは変わります。

共通の初期コミットから、mainは説明書、featureは機能ファイル、releaseは設定ファイルを追加した状態で始めます。featureをmainの上へrebaseし、元の機能変更をreleaseへcherry-pickします。元のコミットはbefore-rebaseタグで参照できるようにしてあります。

変更内容の同一性とコミットの同一性を分け、再適用後の親・ファイル構成・履歴を確認します。

1三つに分かれた開始状態

各ブランチとタグを含む履歴を表示します。現在はfeatureです。

git log --graph --all全参照からたどれる履歴を表示する --oneline --decorateブランチとタグの名前を付ける

initialから3方向へ履歴が分かれています。before-rebaseは現在のfeatureのコミットを指し、後で載せ直す前後を比較する目印になります。

2featureが追加した変更

共通祖先からfeatureの差分を表示します。

git diff main...feature共通祖先以降のfeatureの変更を読む

feature.txtにbetaを1行追加した変更です。mainの説明書とは別ファイルなので、この例では同じ箇所の競合なしで再適用できます。

3mainの上へ載せ直す

featureの変更をmainの先へrebaseします。コマンド後に、新しい親と件名を表示します。

git rebase -q main現在のfeatureをmainの上へ再適用する git log feature --format="%h parent=%p各コミットの親IDを表示する %s"

featureの親がmainの説明書追加コミットになりました。初期コミットを親に持っていた元のfeatureとは、別のコミットです。

4親が違っても機能ファイルは同じ

機能ファイルの内容差と、新旧の親IDを確認します。

git diff before-rebase feature -- feature.txt機能ファイルの新旧を比較する git rev-parse before-rebase^ feature^ main元の親・新しい親・mainを順に解決する

feature.txtの差分は出ません。最初の親IDはinitial、次の二つはmainのIDで一致します。変更対象の内容は保ちつつ、基点が変わっています。

5全ファイルが同一とは限らない

今度はファイルを限定せずに、載せ直す前後を比較します。

git diff --stat全体の変更ファイルと行数を表示する before-rebase feature git show feature:README.md新しい基点から継承した内容を読む

新しいfeatureにはmainから継承したREADME.mdが加わっています。機能パッチが同じことと、コミット全体のファイル構成が同じことは別です。

6パッチ列の対応を確認

range-diffで、旧基点から旧feature、新基点から新featureという二つの変更列を比較します。

git range-diff二つのコミット列のパッチを比較する initial..before-rebase main..feature旧系列と新系列の範囲

対応するコミットに=が付きます。この例ではパッチが等しくても、コミットIDは異なります。rebase後はIDだけでなく変更の内容も確認します。

7一つの変更をreleaseへ適用

releaseへ切り替え、元のfeatureの変更だけを適用します。

git switch release適用先へ切り替える git cherry-pick before-rebase指定コミットの変更を適用する git log -2 --format="%h parent=%p %s"

release設定のコミットを親に持つ、新しい機能追加コミットができます。mainの説明書追加を一緒に取り込む操作ではありません。

8適用先ごとのファイル構成

releaseとfeatureにあるファイルを列挙します。

git ls-tree --name-only releasereleaseのファイル構成 git ls-tree --name-only featurefeatureのファイル構成 git diff release feature -- feature.txt機能ファイルだけの内容差

releaseにはrelease.txt、featureにはREADME.mdがあります。feature.txtの差分はありません。同じ機能変更が、異なる基点に載っている状態です。

9元のコミットも参照できる

最後に元のタグと、新しいfeature・releaseのIDを確認します。

git rev-parse before-rebase feature release三つのコミットIDを表示する git log --graph --all再適用後の全体の関係を読む --oneline --decorate

同じ機能追加でも3個のコミットIDがあります。元のコミットはタグから参照できるため、この例では履歴に残っています。共有済みの履歴を載せ直すと他者の参照と分かれるため、共同作業では更新方針の合意が必要です。

まとめ

rebaseとcherry-pickは、変更を別の基点へ適用して新しいコミットを作ります。

親や基点が異なるため、パッチが同じでもIDと全体のファイル構成は変わります。

元の参照と再適用後を比較し、意図した変更だけが含まれているか確認します。

操作履歴と解説を振り返れます。

Git / シェル

1
git log --graph --all --oneline --decorate
* b5f7c0f (HEAD -> feature, tag: before-rebase) Add feature file
| * e98026c (main) Add main documentation
|/  
| * dd02e64 (release) Add release configuration
|/  
* dfaf585 (tag: initial) Initial files
2
git diff main...feature
diff --git a/feature.txt b/feature.txt
new file mode 100644
index 0000000..65b2df8
--- /dev/null
+++ b/feature.txt
@@ -0,0 +1 @@
+beta
3
git rebase -q main git log feature --format="%h parent=%p %s"
69a412b parent=e98026c Add feature file
e98026c parent=dfaf585 Add main documentation
dfaf585 parent= Initial files
4
git diff before-rebase feature -- feature.txt git rev-parse before-rebase^ feature^ main
dfaf585ee68990808a5f4c486d0007de53bee54d
e98026c7506c02518bd2ebc1e9b3b5db6191d55a
e98026c7506c02518bd2ebc1e9b3b5db6191d55a
5
git diff --stat before-rebase feature git show feature:README.md
 README.md | 1 +
 1 file changed, 1 insertion(+)
main documentation
6
git range-diff initial..before-rebase main..feature
1:  b5f7c0f = 1:  69a412b Add feature file
7
git switch release git cherry-pick before-rebase git log -2 --format="%h parent=%p %s"
Switched to branch 'release'
[release 3f483d9] Add feature file
 Date: Sun Nov 1 09:00:00 2026 +0900
 1 file changed, 1 insertion(+)
 create mode 100644 feature.txt
3f483d9 parent=dd02e64 Add feature file
dd02e64 parent=dfaf585 Add release configuration
8
git ls-tree --name-only release git ls-tree --name-only feature git diff release feature -- feature.txt
feature.txt
note.txt
release.txt
README.md
feature.txt
note.txt
9
git rev-parse before-rebase feature release git log --graph --all --oneline --decorate
b5f7c0fd934a53b9eccdcf8b8d5ab8a9dcd0b040
69a412b6599e1cffec5d123677c81defbc8ce744
3f483d9a860dc02e008e01b015545260d0f4c13d
* 69a412b (feature) Add feature file
* e98026c (main) Add main documentation
| * 3f483d9 (HEAD -> release) Add feature file
| * dd02e64 Add release configuration
|/  
| * b5f7c0f (tag: before-rebase) Add feature file
|/  
* dfaf585 (tag: initial) Initial files

演習完了