threads / discuss / 19342

Re: [Q] merge squash unexpected conflicts

Subject: Re: [Q] merge squash unexpected conflicts

## tl;dr

11 messages between May 14, 2009 and May 14, 2009.

replies: 10people: 4as markdown or json

Cory Sharp· May 14, 2009, 02:42 UTC · lore

Using git 1.6.3.1, when using "git merge --squash" I get unexpected conflicts when merging an update to a file that was added after the original branch point, like this

  * Initialize git repo
  * Add hello to master
  * Create topic branch
  * Add goodbye to master
  * Merge squash master into topic, gets new goodbye
  * Update goodbye in master
  * Again merge squash master into topic, update goodbye
The second merge squash produces a conflict in goodbye.

Am I doing something a little wrong or unexpected?  Is there a way around this squash conflict behavior?  This doesn't seem to happen with plain merge without squash. I've appended a small bash script to show this behavior - run it from an empty directory.

Thanks, Cory

#!/bin/sh
try() {
    echo "$@"
    "$@" || exit 1
}
note() {
    echo
    echo "##" "$@" "##"
}
[ -d .git ] && echo .git already exists, aborting. && exit 1

note "Initialize git repo" try git init

note "Add hello to master" echo "hello world" > hello.txt try git add hello.txt try git commit -m "Added hello"

note "Create topic branch" try git checkout -b topic

note "Add goodbye to master" try git checkout master echo "farewell world" > goodbye.txt try git add goodbye.txt try git commit -m "Added goodbye"

note "Merge master into topic, gets new goodbye" try git checkout topic try git merge --squash master try git commit -m "Merged master"

note "Update goodbye in master" try git checkout master echo "goodbye world" > goodbye.txt try git add goodbye.txt try git commit -m "Updated goodbye"

note "Again merge master into topic, update goodbye" try git checkout topic try git merge --squash master

Junio C Hamano· May 14, 2009, 03:21 UTC · re: Cory Sharp · lore
Cory Sharp <cory.sharp@gmail.com> writes:
> Am I doing something a little wrong or unexpected?  Is there a way
> around this squash conflict behavior?  This doesn't seem to happen
> with plain merge without squash.
Of course.  That's the whole point of recording a merge as a merge.
Cory Sharp· May 14, 2009, 03:57 UTC · re: Junio C Hamano · lore
On Wed, May 13, 2009 at 8:21 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 8 quoted lines
> Cory Sharp <cory.sharp@gmail.com> writes:
>
>> Am I doing something a little wrong or unexpected?  Is there a way
>> around this squash conflict behavior?  This doesn't seem to happen
>> with plain merge without squash.
>
> Of course.  That's the whole point of recording a merge as a merge.
>
$ git help merge
  --squash
           Produce the working tree and index state as if a real merge
happened. ... This allows you to create a
           single commit on top of the current branch whose effect is
the same as merging another branch.
Junio C Hamano· May 14, 2009, 04:42 UTC · re: Cory Sharp · lore
Cory Sharp <cory.sharp@gmail.com> writes:
Show 12 quoted lines
> On Wed, May 13, 2009 at 8:21 PM, Junio C Hamano <gitster@pobox.com> wrote:
> ..
>> Of course.  That's the whole point of recording a merge as a merge.
>>
>
> $ git help merge
>
>   --squash
>            Produce the working tree and index state as if a real merge
> happened. ... This allows you to create a
>            single commit on top of the current branch whose effect is
> the same as merging another branch.
What's your point?

WIth --squash, the tree and the index state becomes the same as if a real merge happened. But the merge history is discarded with --squash. It is a simulation of a merge in CVS and SVN (before they added "merge tracking").

If you want support for repeated merges by merge tracking, you do not want todiscard the merge history by using --squash.

Cory Sharp· May 14, 2009, 06:34 UTC · re: Junio C Hamano · lore
On Wed, May 13, 2009 at 9:42 PM, Junio C Hamano <gitster@pobox.com> wrote:
> What's your point?
I am asking for help and understanding.
Show 6 quoted lines
> WIth --squash, the tree and the index state becomes the same as if a real
> merge happened.  But the merge history is discarded with --squash.  It is
> a simulation of a merge in CVS and SVN (before they added "merge tracking").
>
> If you want support for repeated merges by merge tracking, you do not want
> todiscard the merge history by using --squash.

Why doesn't --squash do merge tracking? The help didn't indicate that it doesn't, and I don't understand why it shouldn't -- since I *could* track the previous merge point manually and do "git diff --binary PREV_MERGE..NEXT_MERGE | git apply -" to do the merge myself.

But since that's me manually performing merge tracking, why doesn't "merge --squash" track like just "merge" does? If I didn't want tracking, I would expect to use some other command than "git merge [options]".

Thanks for your help, Cory

Junio C Hamano· May 14, 2009, 06:42 UTC · re: Cory Sharp · lore
Cory Sharp <cory.sharp@gmail.com> writes:
Show 5 quoted lines
>> If you want support for repeated merges by merge tracking, you do not want
>> todiscard the merge history by using --squash.
>
> Why doesn't --squash do merge tracking?  The help didn't indicate that
> it doesn't, and I don't understand why ...

Because "merge" is (no surprise) what tracks what (two or more) things were merged. And with --squash you are choosing not to make a merge. I am not sure if there is any more thing to be explained...

Cory Sharp· May 14, 2009, 06:54 UTC · re: Junio C Hamano · lore
On Wed, May 13, 2009 at 11:42 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Because "merge" is (no surprise) what tracks what (two or more) things
> were merged.  And with --squash you are choosing not to make a merge.  I
> am not sure if there is any more thing to be explained...
Yeah I'm not quite getting it.  Thanks for trying to explain, though.
Michael Radziej· May 14, 2009, 07:01 UTC · re: Cory Sharp · lore
On Wed, May 13, Cory Sharp wrote:
> Yeah I'm not quite getting it.  Thanks for trying to explain, though.

git merge --squash is not a merge at all. It only creates a regular commit with one parent. It is useful only in very special circumstances.

Michael
-- 
noris network AG - Deutschherrnstraße 15-19 - D-90429 Nürnberg -
Tel +49-911-9352-0 - Fax +49-911-9352-100
http://www.noris.de - The IT-Outsourcing Company
 
Vorstand: Ingo Kraupa (Vorsitzender), Joachim Astel, Hansjochen Klenk - 
Vorsitzender des Aufsichtsrats: Stefan Schnabel - AG Nürnberg HRB 17689
Cory Sharp· May 14, 2009, 18:25 UTC · re: Michael Radziej · lore
On Thu, May 14, 2009 at 12:01 AM, Michael Radziej <mir@noris.de> wrote:
> git merge --squash is not a merge at all. ...
> It is useful only in very special circumstances.

You're right. I (incorrectly) thought I had to use --squash to properly interface with an svn branch and trunk through git-svn. I thought not using squash would trigger hundreds of commits - it doesn't, nice things happen with just "merge".

Thanks everyone for helping me, Cory

Michael J Gruber· May 14, 2009, 12:17 UTC · re: Cory Sharp · lore
Cory Sharp venit, vidit, dixit 14.05.2009 05:57:
Show 17 quoted lines
> On Wed, May 13, 2009 at 8:21 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Cory Sharp <cory.sharp@gmail.com> writes:
>>
>>> Am I doing something a little wrong or unexpected?  Is there a way
>>> around this squash conflict behavior?  This doesn't seem to happen
>>> with plain merge without squash.
>>
>> Of course.  That's the whole point of recording a merge as a merge.
>>
> 
> $ git help merge
> 
>   --squash
>            Produce the working tree and index state as if a real merge
> happened. ... This allows you to create a
>            single commit on top of the current branch whose effect is
> the same as merging another branch.
The problem is simply in the "...". You cut out the vital part:
        but do not actually make a commit or
        move the `HEAD`, nor record `$GIT_DIR/MERGE_HEAD` to
        cause the next `git commit` command to create a merge
        commit.
See? Tree: yes, index: yes, merge info: no.

Git does perform a (tree) merge with --squash, but records the resulting tree as an ordinary non-merge commit (with a single parent).

I'm not sure whether the statement about the index is completely correct, though. During a merge the index records info about the merge (stages :1: etc.) but that as missing with --squash. Only the resulting tree is added to the index. How about the below?

Michael
diff --git a/Documentation/merge-options.txt
b/Documentation/merge-options.txt
index 637b53f..adadf8e 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -39,7 +39,8 @@

 --squash::
        Produce the working tree and index state as if a real
-       merge happened, but do not actually make a commit or
+       merge happened (except for the merge information),
+       but do not actually make a commit or
        move the `HEAD`, nor record `$GIT_DIR/MERGE_HEAD` to
        cause the next `git commit` command to create a merge
        commit.  This allows you to create a single commit on
Cory Sharp· May 14, 2009, 14:47 UTC · re: Michael J Gruber · lore

On Thu, May 14, 2009 at 5:17 AM, Michael J Gruber <git@drmicha.warpmail.net> wrote:

Show 36 quoted lines
> Cory Sharp venit, vidit, dixit 14.05.2009 05:57:
>> On Wed, May 13, 2009 at 8:21 PM, Junio C Hamano <gitster@pobox.com> wrote:
>>> Cory Sharp <cory.sharp@gmail.com> writes:
>>>
>>>> Am I doing something a little wrong or unexpected?  Is there a way
>>>> around this squash conflict behavior?  This doesn't seem to happen
>>>> with plain merge without squash.
>>>
>>> Of course.  That's the whole point of recording a merge as a merge.
>>>
>>
>> $ git help merge
>>
>>   --squash
>>            Produce the working tree and index state as if a real merge
>> happened. ... This allows you to create a
>>            single commit on top of the current branch whose effect is
>> the same as merging another branch.
>
> The problem is simply in the "...". You cut out the vital part:
>
>
>        but do not actually make a commit or
>        move the `HEAD`, nor record `$GIT_DIR/MERGE_HEAD` to
>        cause the next `git commit` command to create a merge
>        commit.
>
> See? Tree: yes, index: yes, merge info: no.
>
> Git does perform a (tree) merge with --squash, but records the resulting
> tree as an ordinary non-merge commit (with a single parent).
>
> I'm not sure whether the statement about the index is completely
> correct, though. During a merge the index records info about the merge
> (stages :1: etc.) but that as missing with --squash. Only the resulting
> tree is added to the index. How about the below?

Now I see, thanks for the help. The elided part, at the time I elided it, did not make me understand that merge info was not written, particularly when surrounded by its original accompanying text.

Thanks again, Cory

← back to recent threads