2

From the documentation of git rebase:

The current branch is reset to , or if the --onto option was supplied. This has the exact same effect as git reset --hard (or ). ORIG_HEAD is set to point at the tip of the branch before the reset.

The commits that were previously saved into the temporary area are then reapplied to the current branch, one by one, in order. Note that any commits in HEAD which introduce the same textual changes as a commit in HEAD.. are omitted (i.e., a patch already accepted upstream with a different commit message or timestamp will be skipped).

Then the important bit:

It is possible that a merge failure will prevent this process from being completely automatic

I can see how that happens in general, but I have a case were it seems to have happened oddly.

Here are my commands:

407  07/09/18 16:53:09 cd temp
  408  07/09/18 16:53:16 git clone https://github.com/joereddington/todo.txt
  410  07/09/18 16:53:35 cd todo.txt/
  412  07/09/18 16:53:41 git rebase HEAD~20

I feel like this CAN'T possibly fail. My understanding is that the sequence is:

  • Move HEAD to HEAD~20
  • Put the 20 most recent commits into a tempory area
  • in order, reapply commits that have already been done to a repo that has the same state
  • End

But I get an error:

Applying: update Using index info to reconstruct a base tree... M   todo.txt .git/rebase-apply/patch:21: trailing whitespace. (A) Apply for gift aid number  .git/rebase-apply/patch:30: trailing whitespace. (C) Sort all the 'to sort' spending in the right categories in the expenditure against grant file.  .git/rebase-apply/patch:76: trailing whitespace. (E) Go thought calendar and find at least one 'thank you's you *can* make  warning: 3 lines add whitespace errors. Falling back to patching base and 3-way merge... Auto-merging todo.txt CONFLICT (content): Merge conflict in todo.txt error: Failed to merge in the changes. Patch failed at 0025 update The copy of the patch that failed is found in: .git/rebase-apply/patch

Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort".

Josephs-Mini:todo.txt josephreddington$

How can this happen? It's refusing to execute a commit on content that it has already executed the same changes on!

Joe
  • 4,367
  • 7
  • 33
  • 52
  • `git branch --contains 0fd691acb0b44d9621bbdf75779790ca14d86ef0` shows that this commit is already in master.... why rebase it? – Michael H. Sep 07 '18 at 09:53
  • So my use case is that I have a script that I want to on every version of the code. So I've been using git rebase --interactive --exec scriptname - but that ran into a problem and when debuging I found the above - which I didn't understand so wanted to ask a question about - does that make sense? – Joe Sep 07 '18 at 09:55
  • 1
    That's fine. I'm sure there are other ways to achieve that goal but it's still a valid question to understand what's breaking in your example. – Michael H. Sep 07 '18 at 10:31

1 Answers1

0

This question is based on a out-of-date understanding of version control systems.

Systems like CVS and SVN stored commits as deltas - the commit was literally the list of differences from the previous version. If git worked the same way then it would make sense that this rebasing would be completely without errors.

Git doesn't work like that (there is some delta compression under the hood). Git stores a snapshot of what your files look like each time. This means that if there are any merges in the rebasing, then it doesn't know what to do about them - when rebasing a merge git has three different file systems to compare and wants some guidance (in this case the heuristic 'make it look exactly like the next link in the chain' would be fine, but that's an edge case).

To solve the example as presented, the switch '--preserve-merges' fixes the problem.

Joe
  • 4,367
  • 7
  • 33
  • 52
  • I had started on a long answer, but yes, this is part of it. It's also important to realize that rebase works by *copying* commits (so as to use the new and improved commits instead of the old ones). If you want to run *tests* against the *old* commits, you don't want to use rebase at all. Using `--preserve-merges` can work for your particular case, but is not the right approach: consider using `git bisect` instead. – torek Sep 07 '18 at 19:36
  • @torek - I can absolutely see why that would be the case - I was more focused on working out how the case even came up. (I'm also fairly mystified about the downvoting... I think SE culture has changed since last time I was asking questions and I've clearly NOT moved in the same way) – Joe Sep 10 '18 at 08:37