Background:
- I want to contribute a bug fix to a project that uses Git for version control;
- I don't have write access to the project's public repository;
- the project maintainer requires patches to be submitted via email.
Workflow:
- I clone the project's public repository;
- I create a local branch in which I develop my bug fix;
- I email the patch to the maintainer;
- the maintainer applies the patch and pushes to the project's public repository;
- I pull the changes to my local
master
branch fromorigin/master
; - I confirm that my patch was applied by the maintainer.
Problem:
git branch -d
won't now delete my bug fix branch, givingerror: The branch ... is not fully merged.
However, the patch that the maintainer applied contained all the changes that I had made in my bug fix branch, so intuitively it seems wrong that Git should claim that the branch "is not fully merged."
The Git book seems to agree with me. It mentions only one reason why git branch -d
would fail - because the branch "contains work that isn’t merged in yet" - which doesn't apply in my case.
I am unsure whether I have encountered a bug in Git, or whether Git just doesn't support my use-case.
Yes, I could just go ahead and delete the branch using git branch -D
, but I would rather not get into the habit of doing that except in cases where I want to delete a branch whose changes to the files in the working tree really have not been merged into any other branch.
I would much rather:
- understand why Git is claiming that the bug fix branch "is not fully merged" even though the branch's changes have indeed been applied to
master
, and - find a more elegant response than resorting to
git branch -D
.
Example
$ 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
I then email 0001-Fix-bug-42.patch
to the maintainer.
The maintainer applies this using git am < 0001-Fix-bug-42.patch
, maybe makes some other commits too, and pushes to origin/master.
I then do:
$ 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
So far, so good! Let's see if my patch was applied in one of those three commits:
$ 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
Looks like it was applied in the penultimate commit. Let's confirm that!
$ diff -s <(git diff @^^ @^) <(git diff fix_bug_42^ fix_bug_42)
Files /dev/fd/63 and /dev/fd/62 are identical
$
All the changes I made in my fix_bug_42
branch have definitely been applied and committed by the maintainer. Yay!
That means Git should know it is now safe for me to delete my bug fix branch, right? Wrong!
$ 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'.
Argh!
Hypotheses
Now, I think I know why this is happening. I think it is because the commit in master
in which my patch was applied (44a35eae3dc69002b6d3484cd17ad653ee7de3c3) has a different hash to the commit in fix_bug_42
from which that patch was made (244540f...). I.e. Git thinks that because commit 244540f doesn't exist in master
, that means fix_bug_42
"is not fully merged".
Questions
Is my hypothesis correct?
Regardless, what can I do about this problem, short of using
git branch -D
? (E.g. is there a better workflow I could have used, that would have avoided this problem?)Does this unexpected (to me, at least) behaviour from Git represent either a bug in Git, or at least a legitimate feature request for improved handling of this use case?