I have two branches master
which is the main branch and feature_branch_1
which is very old and many commits behind the master. I need to merge feature_branch_1
into master, so I did:
git pull --rebase origin master
As expected there are tons of conflicts, soon after there was a need to develop another feature on a new feature_branch_2
and this is against the HEAD
of master and definitely needs to be worked on before feature_branch_1
. Being more or less in the middle of the complex merge, how do I do a temporary commit on feature_branch_1
so I can come back to it later. I know I can just do a:
git add <things-that-are-done>
git commit -m 'intermediary commit between merges'
... come back to it later
git checkout 'that-temp-commit-hash'
... after finishing
git add .
git commit -m 'done with feature_branch_1'
git rebase --interactive HEAD~1
making a temporary commit then rebasing to squash it afterward.
is this the best way to handle this?
Git will not let you make a commit with an index that contains unmerged entries.
Using git add
will resolve away the unmerged entries, so that you can then commit, but this approach may be unsatisfactory for several reasons. Without going into too much detail:
- Unresolved paths are indicated by the use of index slots 1-3 instead of slot 0. These hold the merge-base version of the file, and both "sides" (
--ours
and --theirs
, although during a rebase the roles are kind of swapped) of the merge.
git add
copies from the work-tree to slot 0, clobbering slots 1-3, so that the file is now resolved (even if the work-tree file is still full of conflict markers).
- An "undo" (
REUC
) entry is recorded in the index at this point as well, so that you can git checkout -m
the path to re-create the conflict (wiping away the slot 0 entry and restoring the 1-3 entries).
- Actually committing the merge result loses the undo state permanently.
This means that if you do commit a partial merge, and then want to go back to it and want to finish it, some information—specifically the unmerged state, even if it was moved to an undo entry—is missing. The closest you can get to figuring out, later, which files you still need to merge properly, is to search for conflict markers. (If that's OK with you, this method may be satisfactory after all.)
Besides this, a rebase copies multiple commits, and you have not mentioned whether this particular merge conflict has occurred on the very last such commit. You need to either finish or abort the rebase before going on to other operations. (It's technically possible to do some things in the middle of a rebase, but this is tricky.)
As for this part:
... come back to it later
git checkout 'that-temp-commit-hash'
... after finishing
git add .
git commit -m 'done with feature_branch_1'
git rebase --interactive HEAD~1
Because this particular unmerged-state (which you quickly resolved "wrong" on purpose so as to do something else and come back later) was the result of a rebase rather than a merge, that sequence could work. It would be simpler, and more generally applicable, to replace the last two steps with git commit --amend
, though. The --amend
option tells git commit
to make its new commit using the current commit's parent(s), instead of the current commit itself. This works for both normal (single-parent, non-merge) commits and actual merges (two or more parents).
Alternatives
Your best bet is probably to leave this work-tree alone and make another one where you handle the other issues.
The simplest way to do that, which always works with every version of Git, is to make another clone.
You can make the extra clone by cloning the in-progress rebase. On sensible systems that have hard links, if you clone your repository to another repository on the same file system, using local paths (git clone work/repo work/new-clone-for-fast-fix
for instance, from one level up from where you have been working), Git will use hard links to the underlying packs and objects, so that you need only work-tree space.
If your Git is relatively new (I recommend at least Git 2.6 although the feature was there in 2.5), you can use git worktree add
to create a new "linked work-tree". A linked work-tree remembers its origin repository (and vice versa), but also has a private index / staging-area. You can put it on whatever branch you want and do anything you like there, including creating other branches or doing other rebases, all without disturbing your "main" work-tree and "main" index.