git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* Do not raise conflict when a code in a patch was already added
@ 2018-08-20 10:22 Konstantin Kharlamov
  2018-08-20 17:40 ` Phillip Wood
  0 siblings, 1 reply; 5+ messages in thread
From: Konstantin Kharlamov @ 2018-08-20 10:22 UTC (permalink / raw)
  To: git

So, steps-to-reproduce below rather full of trivia like setting up a
repo, but the TL;DR is:

Upon using `git rebase -i HEAD~1` and then `git add -p` to add part of a
"hunk" as one commit, and then using `git rebase --continue` so the
other part of hunk would be left in top commit; git raises a conflict.

It's spectacular, that content of one of inserted conflict markers is
empty, so all you have to do is to remove the markers, and use `git add`
on the file, and then `git rebase --continue`

Its a lot of unncessary actions, git could just figure that the code it
sees in the patch is already there, being a part of another commit.

Maybe git could issue a warning, or to question a user interactively 
(y/n); but raising a conflict IMO is unnecessary.

# Steps to reproduce

In empty dir execute:

	$ git init
	$ touch test
	Initialized empty Git repository in /tmp/test/.git/
	$ git add test
	$ git commit
	[master (root-commit) a7ce543] 1st commit
	 1 file changed, 2 insertions(+)
	 create mode 100644 test
	$ echo -e "foo\nbar" > test             # content you'll want to break
	$ git add -u && git commit
	[detached HEAD 9e28331] 2-nd commit
	 1 file changed, 2 insertions(+)
	$ git rebase -i --root
	Stopped at a7ce543...  1st commit
	You can amend the commit now, with

	  git commit --amend

	Once you are satisfied with your changes, run

	  git rebase --continue

Put "edit" for the 2-nd commit

	$ git reset HEAD^
	Unstaged changes after reset:
	M       test
	$ git add -p
	diff --git a/test b/test
	index e69de29..3bd1f0e 100644
	--- a/test
	+++ b/test
	@@ -0,0 +1,2 @@
	+foo
	+bar
	Stage this hunk [y,n,q,a,d,e,?]? e

	╭─constantine@constantine-N61Ja  /tmp/test ‹node-›  ‹› (e721fa3*)
	╰─$ git commit
	[detached HEAD 27b2f63] add foo
	 1 file changed, 1 insertion(+)
	╭─constantine@constantine-N61Ja  /tmp/test ‹node-›  ‹› (27b2f63*)
	╰─$ git rebase --continue
	test: needs update
	You must edit all merge conflicts and then
	mark them as resolved using git add

What happened is that it's obvious that the hunk was broken to multiple
commits, and git should figure that out, and not to raise a conflict.

Side note: for some reason in the test git didn't insert conflict
markers. It did in real-world usecase though, and there was simply no
content inside one of them.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Do not raise conflict when a code in a patch was already added
  2018-08-20 10:22 Do not raise conflict when a code in a patch was already added Konstantin Kharlamov
@ 2018-08-20 17:40 ` Phillip Wood
  2018-08-20 19:22   ` Johannes Sixt
  0 siblings, 1 reply; 5+ messages in thread
From: Phillip Wood @ 2018-08-20 17:40 UTC (permalink / raw)
  To: Konstantin Kharlamov, git

On 20/08/2018 11:22, Konstantin Kharlamov wrote:
> So, steps-to-reproduce below rather full of trivia like setting up a
> repo, but the TL;DR is:
> 
> Upon using `git rebase -i HEAD~1` and then `git add -p` to add part of a
> "hunk" as one commit, and then using `git rebase --continue` so the
> other part of hunk would be left in top commit; git raises a conflict.

I think this is a misleading error message as in your example below
there are no conflicts, just unstaged changes. git-rebase.sh has the
following code


git update-index --ignore-submodules --refresh &&
        git diff-files --quiet --ignore-submodules || {
                echo "$(gettext "You must edit all merge conflicts and then
mark them as resolved using git add")"
                exit 1

I think this pre-dates interactive rebases when the only unstaged
changes could be conflicts.

> 
> It's spectacular, that content of one of inserted conflict markers is
> empty, so all you have to do is to remove the markers, and use `git add`
> on the file, and then `git rebase --continue`
> 
> Its a lot of unncessary actions, git could just figure that the code it
> sees in the patch is already there, being a part of another commit.

If there are conflict markers where one side is empty it means that some
lines from the merge base (which for a rebase is the parent of the
commit being picked) have been deleted on one side and modified on the
other. Git cannot know if you want to use the deleted version or the
modified version. You can use 'git diff --cc' to see the combined diff
which should show the lines being deleted on both sides and an addition
on the side with the modified lines. You can also set the
merge.conflictStyle config variable to diff3 to see the original text as
well as the text from the merge heads.

Best Wishes

Phillip

> 
> Maybe git could issue a warning, or to question a user interactively
> (y/n); but raising a conflict IMO is unnecessary.
> 
> # Steps to reproduce
> 
> In empty dir execute:
> 
>     $ git init
>     $ touch test
>     Initialized empty Git repository in /tmp/test/.git/
>     $ git add test
>     $ git commit
>     [master (root-commit) a7ce543] 1st commit
>      1 file changed, 2 insertions(+)
>      create mode 100644 test
>     $ echo -e "foo\nbar" > test             # content you'll want to break
>     $ git add -u && git commit
>     [detached HEAD 9e28331] 2-nd commit
>      1 file changed, 2 insertions(+)
>     $ git rebase -i --root
>     Stopped at a7ce543...  1st commit
>     You can amend the commit now, with
> 
>       git commit --amend
> 
>     Once you are satisfied with your changes, run
> 
>       git rebase --continue
> 
> Put "edit" for the 2-nd commit
> 
>     $ git reset HEAD^
>     Unstaged changes after reset:
>     M       test
>     $ git add -p
>     diff --git a/test b/test
>     index e69de29..3bd1f0e 100644
>     --- a/test
>     +++ b/test
>     @@ -0,0 +1,2 @@
>     +foo
>     +bar
>     Stage this hunk [y,n,q,a,d,e,?]? e
> 
>     ╭─constantine@constantine-N61Ja  /tmp/test ‹node-›  ‹› (e721fa3*)
>     ╰─$ git commit
>     [detached HEAD 27b2f63] add foo
>      1 file changed, 1 insertion(+)
>     ╭─constantine@constantine-N61Ja  /tmp/test ‹node-›  ‹› (27b2f63*)
>     ╰─$ git rebase --continue
>     test: needs update
>     You must edit all merge conflicts and then
>     mark them as resolved using git add
> 
> What happened is that it's obvious that the hunk was broken to multiple
> commits, and git should figure that out, and not to raise a conflict.
> 
> Side note: for some reason in the test git didn't insert conflict
> markers. It did in real-world usecase though, and there was simply no
> content inside one of them.
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Do not raise conflict when a code in a patch was already added
  2018-08-20 17:40 ` Phillip Wood
@ 2018-08-20 19:22   ` Johannes Sixt
  2018-08-21  9:37     ` Konstantin Kharlamov
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Sixt @ 2018-08-20 19:22 UTC (permalink / raw)
  To: phillip.wood, Konstantin Kharlamov; +Cc: git

Am 20.08.2018 um 19:40 schrieb Phillip Wood:
> On 20/08/2018 11:22, Konstantin Kharlamov wrote:
>> It's spectacular, that content of one of inserted conflict markers is
>> empty, so all you have to do is to remove the markers, and use `git add`
>> on the file, and then `git rebase --continue`
>>
>> Its a lot of unncessary actions, git could just figure that the code it
>> sees in the patch is already there, being a part of another commit.
> 
> If there are conflict markers where one side is empty it means that some
> lines from the merge base (which for a rebase is the parent of the
> commit being picked) have been deleted on one side and modified on the
> other. Git cannot know if you want to use the deleted version or the
> modified version.

There's another possibility (and I think it is what happens actually in 
Konstantin's case): When one side added lines 1 2 and the other side 
added 1 2 3, then the actual conflict is << 1 2 == 1 2 3 >>, but our 
merge code is able to move the identical part out of the conflicted 
section: 1 2 << == 3 >>. But this is just a courtesy for the user; the 
real conflict is the original one. Without this optimization, the work 
to resolve the conflict would be slightly more arduous.

-- Hannes

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Do not raise conflict when a code in a patch was already added
  2018-08-20 19:22   ` Johannes Sixt
@ 2018-08-21  9:37     ` Konstantin Kharlamov
  2018-08-21 12:10       ` Igor Djordjevic
  0 siblings, 1 reply; 5+ messages in thread
From: Konstantin Kharlamov @ 2018-08-21  9:37 UTC (permalink / raw)
  To: Johannes Sixt, phillip.wood; +Cc: git



On 20.08.2018 22:22, Johannes Sixt wrote:
> Am 20.08.2018 um 19:40 schrieb Phillip Wood:
>> On 20/08/2018 11:22, Konstantin Kharlamov wrote:
>>> It's spectacular, that content of one of inserted conflict markers is
>>> empty, so all you have to do is to remove the markers, and use `git add`
>>> on the file, and then `git rebase --continue`
>>>
>>> Its a lot of unncessary actions, git could just figure that the code it
>>> sees in the patch is already there, being a part of another commit.
>>
>> If there are conflict markers where one side is empty it means that some
>> lines from the merge base (which for a rebase is the parent of the
>> commit being picked) have been deleted on one side and modified on the
>> other. Git cannot know if you want to use the deleted version or the
>> modified version.
> 
> There's another possibility (and I think it is what happens actually in 
> Konstantin's case): When one side added lines 1 2 and the other side 
> added 1 2 3, then the actual conflict is << 1 2 == 1 2 3 >>, but our 
> merge code is able to move the identical part out of the conflicted 
> section: 1 2 << == 3 >>. But this is just a courtesy for the user; the 
> real conflict is the original one. Without this optimization, the work 
> to resolve the conflict would be slightly more arduous.

Yeah, thanks, that's what happens. And I'm wondering, is it really 
needed to raise a conflict there? Would it be worth to just apply the 
line "3", possibly with a warning or an interactive question to user 
(apply/raise) that identical parts were ignored?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Do not raise conflict when a code in a patch was already added
  2018-08-21  9:37     ` Konstantin Kharlamov
@ 2018-08-21 12:10       ` Igor Djordjevic
  0 siblings, 0 replies; 5+ messages in thread
From: Igor Djordjevic @ 2018-08-21 12:10 UTC (permalink / raw)
  To: Konstantin Kharlamov, Johannes Sixt, phillip.wood; +Cc: git

Hi Konstantin,

On 21/08/2018 11:37, Konstantin Kharlamov wrote:
> 
> > There's another possibility (and I think it is what happens 
> > actually in Konstantin's case): When one side added lines 1 2 and the 
> > other side added 1 2 3, then the actual conflict is 
> > << 1 2 == 1 2 3 >>, but our merge code is able to move the identical 
> > part out of the conflicted section: 1 2 << == 3 >>. But this is just 
> > a courtesy for the user; the real conflict is the original one. 
> > Without this optimization, the work to resolve the conflict would be 
> > slightly more arduous.
> 
> Yeah, thanks, that's what happens. And I'm wondering, is it really 
> needed to raise a conflict there? Would it be worth to just apply the 
> line "3", possibly with a warning or an interactive question to user 
> (apply/raise) that identical parts were ignored?

I see how this might make sense in the given example of "A added 1 
and 2, B added 1 and 2 and 3", but I'm afraid that might be a too 
narrow view.

What we actually don't know is if A deliberately chose not to include 
3, or even worse, if A started from having "1 and 2 and 3" in there, 
and then decided to remove 3.

In both these situation just applying 3 would be wrong, and raising a 
conflict seems as the most (and only?) sensible solution.

Applying _and_ asking for confirmation might be interesting, but I'm 
afraid it would favor specific use case only, being an annoyance in 
all the others (where it should really be a conflict, and you now 
have additional prompt to deal with).

That said, it would indeed be nice to have a way to communicate to 
`git rebase` that we are just splitting later commit into smaller 
parts preceding it, so situations like this could be resolved 
automatically and without conflicts, as you'd expected - but only 
within that narrow, user-provided/communicated context, not in 
general case.

Regards, Buga

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-08-21 12:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-20 10:22 Do not raise conflict when a code in a patch was already added Konstantin Kharlamov
2018-08-20 17:40 ` Phillip Wood
2018-08-20 19:22   ` Johannes Sixt
2018-08-21  9:37     ` Konstantin Kharlamov
2018-08-21 12:10       ` Igor Djordjevic

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).