1

Let's say I'm working on my local repository, and commit often while editing a single file - brandNewFile.txt. So before starting, in the original commit we have just one line of text: "It's a nice day".
Now we add one line at the end of the file, consisting of just the "generic1" text, and create a new commit (A).
This is repeated once more, with a "generic2" line, resulting in commit B. We've ended up with 2 new commits (A and B).

Now before pushing to the remote repository, where everyone has access, I decide that I'd like to cleanup a bit the history, and just keep what I consider to be the meaningful commits related to the operation I was doing.

So I'll do a rebase starting at the original commit, but drop A, while applying (pick) B. As soon as the rebase starts, the following output comes out, following application of B:

Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)

both modified:   brandNewFile.txt

no changes added to commit (use "git add" and/or "git commit -a")

Why would there be a conflict reported, when all I'd like is for one commit that appends one line of text to be placed "on top" of an already existing commit ?
To me it's not a merge operation being attempted, although the outcome sure seems to suggest that this is what's going on.

Mihai Albert
  • 1,288
  • 1
  • 12
  • 27

1 Answers1

0

It is because your initial commit has only one line:

It's a nice day

And commit B has three lines

It's a nice day
generic1
generic2

Now when rebase is merging commit B into initial commit, there is a conflict. Rebase needs to remove line 2 (generic1) from initial commit, but initial commit has only 1 line.

Dhirendra
  • 780
  • 9
  • 26
  • I think my mistake is that I'm thinking in terms of changes induced, as opposed to files modified. The example was a simplification of a more "real" scenario: we start from a file containing a set of functions, then add some text that displays debug info (commit A), then add some improvement to one of the lines of one function (B), then indent some text (C), then remove the debug info entered (D). Out of the 4, I'd like to keep just B and C. Shall I take it that it cannot be done, and the whole string of commits is needed in this case ? – Mihai Albert Oct 12 '18 at 14:43
  • Try resolving the conflicts. They you have explained, there shouldn't be complex conflicts. Otherwise, you can create a new branch from initial state & `cheery-pick` Commit B & C. – Dhirendra Oct 12 '18 at 14:49
  • That would definitely fix it, but I was hoping to have git do this automatically. However for the initial case (where append is being done each time), there can be no commit dropped in the interactive rebase, since this this will essentially break the process, prompting a conflict resolution. – Mihai Albert Oct 12 '18 at 15:06
  • Another thing: when commit B is applied on top of the initial commit, git should only be concerned about getting from the state of the initial file (1 line) to the state of the file in commit B (3 lines). It should be oblivious to the line removed in commit A, that gets dropped anyway. The problem is - I believe - that git can't figure out how to safely ("safely", as in beyond any doubt in regards to the consistency of the result) get from one state to the other. – Mihai Albert Oct 17 '18 at 14:15
  • After a lot of time trying to understand the whole situation - it turns out git also needs the context of a particular change in order to apply it. In my example, "generic2" is indeed the only change introduced by B vs A, however the context around this single change includes "generic1". When git tries to apply the change, it needs the context to successfully perform this, but this is nowhere to be found ("generic1" didn't exist yet in the initial commit). Someone explains it very well here https://stackoverflow.com/questions/33627737/understanding-git-cherry-pick-conflict/36981987#36981987 – Mihai Albert Oct 30 '18 at 15:51