I want to use git rebase
to take a sequence of commits and apply them to a different root commit. For example,
git rebase --onto root start finish
to get the commits from start
to finish
based on root
.
When git cannot apply a commit cleanly, it updates the file to show conflicts like this (example from git manual):
Here are lines that are either unchanged from the common
ancestor, or cleanly resolved because only one side changed.
<<<<<<< yours:sample.txt
Conflict resolution is hard;
let's go shopping.
=======
Git makes conflict resolution easy.
>>>>>>> theirs:sample.txt
And here is another line that is cleanly resolved or unmodified.
The programmer edits the file to what it should be in the new branch, and then runs git --rebase continue
to continue adding the commits from the source.
However, when there are a lot of changes in the file between root
and start
, there may be many lines like this and they may be hard to interpret. In such cases, one might prefer to have the "failed hunks" output to a file, so that one could read through the changes in the original commit (manually making the necessary changes in the file being altered, and then running git rebase --continue
to continue adding commits).
The --reject
option of git apply
does this:
--reject
For atomicity, git apply by default fails the whole patch and does
not touch the working tree when some of the hunks do not apply.
This option makes it apply the parts of the patch that are
applicable, and leave the rejected hunks in corresponding *.rej
files.
This is also the behaviour of the patch
program - so I can get what I want by first outputing the commit with git show
, and then applying it with patch
. This is not convenient when there are many commits involved, however.
Is there any way of doing this with git rebase
(or another git command)?
You can do something like this on a commit-by-commit basis.
When a merge conflict occurs, git gives a message like:
CONFLICT (content): Merge conflict in file.c
Failed to merge in the changes.
Patch failed at 0004 Changes to file
The copy of the patch that failed is found in:
/home/g/src/project/.git/rebase-apply/patch
If file.c is mangled due to showing merge conflicts in the file, you can get the file back to the way it was before the commit with
git reset file.c
git checkout file.c
You can then run
patch -p1 </home/g/src/project/.git/rebase-apply/patch
The output of this could look something like
patching file file.c
Hunk #2 FAILED at 1133.
Hunk #3 FAILED at 1167.
Hunk #4 FAILED at 1201.
Hunk #5 FAILED at 1241.
Hunk #6 FAILED at 1251.
Hunk #7 succeeded at 1324 (offset 6 lines).
Hunk #8 FAILED at 1325.
Hunk #9 succeeded at 2142 (offset 11 lines).
Hunk #10 succeeded at 2163 (offset 11 lines).
Hunk #11 succeeded at 2181 (offset 11 lines).
Hunk #12 succeeded at 2279 (offset 11 lines).
Hunk #13 succeeded at 2299 (offset 11 lines).
Hunk #14 succeeded at 2412 (offset 11 lines).
Hunk #15 succeeded at 2508 (offset 11 lines).
Hunk #16 succeeded at 2531 (offset 11 lines).
Hunk #17 succeeded at 2540 (offset 11 lines).
Hunk #18 succeeded at 2581 (offset 11 lines).
Hunk #19 succeeded at 2599 (offset 11 lines).
Hunk #20 succeeded at 2611 (offset 11 lines).
Hunk #21 succeeded at 2629 (offset 11 lines).
Hunk #22 succeeded at 2637 (offset 11 lines).
Hunk #23 succeeded at 2668 (offset 11 lines).
Hunk #24 succeeded at 2677 (offset 11 lines).
Hunk #25 succeeded at 2805 (offset 11 lines).
Hunk #26 succeeded at 2871 (offset 11 lines).
Hunk #27 succeeded at 2911 (offset 11 lines).
Hunk #28 succeeded at 3028 (offset 11 lines).
Hunk #29 succeeded at 3085 (offset 11 lines).
Hunk #30 succeeded at 3117 (offset 11 lines).
Hunk #31 succeeded at 3557 (offset 11 lines).
Hunk #32 succeeded at 3572 (offset 11 lines).
Hunk #33 succeeded at 4773 (offset 11 lines).
Hunk #34 succeeded at 4807 (offset 11 lines).
Hunk #35 succeeded at 4859 (offset 11 lines).
6 out of 35 hunks FAILED -- saving rejects to file file.c.rej
Then make the changes in file.c.rej manually, then run
git add -u
git rebase --continue
to continue.