バックグラウンド:
- バージョン管理に Git を使用するプロジェクトにバグ修正を提供したいと考えています。
- プロジェクトのパブリック リポジトリへの書き込みアクセス権がありません。
- プロジェクトのメンテナーは、パッチを電子メールで提出することを要求しています。
ワークフロー:
- プロジェクトのパブリック リポジトリのクローンを作成します。
- バグ修正を開発するローカル ブランチを作成します。
- メンテナにパッチをメールで送信します。
- メンテナーはパッチを適用し、プロジェクトのパブリック リポジトリにプッシュします。
master
からローカル ブランチへの変更をプルしorigin/master
ます。- 私のパッチがメンテナーによって適用されたことを確認します。
問題:
git branch -d
バグ修正ブランチを削除しなくなりました。error: The branch ... is not fully merged.
しかし、メンテナーが適用したパッチには、バグ修正ブランチで行ったすべての変更が含まれていたため、Git がブランチが「完全にマージされていない」と主張するのは間違っているように思えます。
Gitの本は私に同意しているようです。git branch -d
失敗する理由は1つだけです-ブランチには「まだマージされていない作業が含まれているため」-私の場合は当てはまりません。
Git でバグに遭遇したのか、それとも Git が私のユースケースをサポートしていないだけなのか、よくわかりません。
はい、先に進んで を使用してブランチを削除することもできますが、作業ツリー内のファイルへの変更が実際にマージされていないgit branch -D
ブランチを削除する場合を除いて、そうする習慣を身につけたくありません。他のブランチ。
私はむしろそうします:
- ブランチの変更が実際に に適用されているにもかかわらず、バグ修正ブランチが「完全にマージされていない」と Git が主張している理由を理解し
master
、 - に頼るよりもエレガントな応答を見つけてください
git branch -D
。
例
$ git clone https://git.example.com/repo.git
# Output omitted for brevity. Clone proceeded fine.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
$ git checkout -b fix_bug_42
Switched to a new branch 'fix_bug_42'
$ vim foo.txt # Fix bug 42.
$ git add foo.txt
$ git commit -m "Fix bug 42"
[fix_bug_42 244540f] Fix bug 42
1 file changed, 1 insertion(+)
$ git format-patch HEAD^
0001-Fix-bug-42.patch
次に、メンテナーにメール0001-Fix-bug-42.patch
します。
メンテナーは を使用してこれを適用しgit am < 0001-Fix-bug-42.patch
、おそらく他のコミットも行い、origin/master にプッシュします。
次に、次のことを行います。
$ git remote update
Fetching origin
remote: Counting objects: 54, done. # Numbers illustrative only
remote: Compressing objects: 100% (42/42), done.
remote: Total 42 (delta 29), reused 0 (delta 0)
Unpacking objects: 100% (42/42), done.
From https://git.example.com/repo
7787ce5..1c1a981 master -> origin/master
$ git status
On branch fix_bug_42
nothing to commit, working directory clean
$ git co master
Switched to branch 'master'
Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
$ git pull
Updating 7787ce5..1c1a981
Fast-forward
bar.txt | 3 +--
contributors.txt | 1 +
foo.txt | 1 +
3 files changed, 3 insertions(+), 2 deletions(-) # Numbers illustrative only
ここまでは順調ですね!私のパッチがこれら 3 つのコミットのいずれかに適用されたかどうかを見てみましょう。
$ git log @...@^^^ # Show the last two commits
commit 1c1a981f0b9cbaa593c949cea07e3265e2f8c9fa
Author: A Maintainer <maintainer@example.com>
Date: Thu Aug 11 20:58:32 2016 +0000
Add sampablokuper to list of contributors
commit 44a35eae3dc69002b6d3484cd17ad653ee7de3c3
Author: Sam Pablo Kuper <sampablokuper@example.edu>
Date: Thu Aug 11 19:00:00 2016 +0000
Fix bug 42
commit 25c3562fecd3f42f76c7552fabec440dd4473c6e
Author: A Maintainer <maintainer@example.com>
Date: Thu Aug 11 14:44:53 2016 +0000
Edit bar.txt
最後から 2 番目のコミットで適用されたようです。それを確認しましょう!
$ diff -s <(git diff @^^ @^) <(git diff fix_bug_42^ fix_bug_42)
Files /dev/fd/63 and /dev/fd/62 are identical
$
私のfix_bug_42
ブランチで行ったすべての変更は、メンテナーによって確実に適用され、コミットされています。わーい!
つまり、Git は、バグ修正ブランチを削除しても安全であることを認識しているはずですよね? 違う!
$ git branch -d fix_bug_42
error: The branch 'fix_bug_42' is not fully merged.
If you are sure you want to delete it, run 'git branch -D fix_bug_42'.
ああ!
仮説
これで、なぜこれが起こっているのかがわかったと思います。私のパッチが適用されたコミット (44a35eaae3dc69002b6d3484cd17ad653ee7de3c3) は、そのパッチが作成されたコミット (244540f...) とは異なるハッシュを持っているためだと思います。つまり、コミット 244540f が に存在しないため、Git は「完全にマージされていない」ことを意味すると考えています。master
fix_bug_42
master
fix_bug_42
質問
私の仮説は正しいですか?
とにかく、使用する以外に、この問題について何ができ
git branch -D
ますか? (たとえば、この問題を回避するために使用できたより良いワークフローはありますか?)Git からのこの予期しない (少なくとも私にとっては) 動作は、Git のバグ、または少なくともこのユースケースの処理を改善するための正当な機能要求のいずれかを表していますか?