Subject: RE: Merging problem

From: <[email-masked]>
Date: Fri, 2 Aug 2024 16:04:03 -0400

On Friday, August 2, 2024 4:01 PM, brian m. carlson wrote:
>On 2024-08-02 at 18:41:48, Michael Salman wrote:
>> I am new to using git and I encountered the following problem
>>
>> 1) Created a repository using Notepad added a file (FileA.txt). Put
>> one line of text in the file. Did a git commit -a. so far so good.
>>
>> 2) I created a branch (my-branch), did a git checkout my-branch
>>
>> 3) Using notepad loaded FileA and changed the first line of text to
>> something else. Gave command git commit -a no problems
>>
>> 4) Git checkout master looked at FileA nothing changed
>>
>> 5) Did a git merge my-branch. No conflict reported
>>
>> 6) Loaded FileA in master the text of the first line had changed to
>> what is in FileA from the branch
>>
>> Your help with this problem would be appreciated. I hope this is not
>> due to my lack of understanding
>
>Let me provide a small shell script that reproduces your report so we can make sure
>we're on the same page.  Here it is:
>
>----
>#!/bin/sh -e
>
>dir="$(mktemp -d)"
>trap 'rm -fr "$dir"' EXIT
>
>cd "$dir"
>git init -b master
>echo "step 1" >FileA.txt
>git add .
>git commit -m 'step 1'
>git checkout -b my-branch
>echo "step 2" >FileA.txt
>git add .
>git commit -m 'step 2'
>git checkout master
>git merge my-branch
>----
>
>Now, let's look at what happens if we add `git log --graph --all --decorate` to the end
>of the script:
>
>----
>* commit 4dd858b4e2b96ec24055d3a19d87e2080c4f1393 (HEAD -> master, my-
>branch)
>| Author: brian m. carlson <[email-masked]>
>| Date:   Fri Aug 2 19:51:42 2024 +0000
>|
>|     step 2
>|
>* commit a1bf54082762cdcffec185d4cf6eef2c753af535
>  Author: brian m. carlson <[email-masked]>
>  Date:   Fri Aug 2 19:51:42 2024 +0000
>
>      step 1
>----
>
>What's happened here is that the commits on `my-branch` are a strict superset of
>the commits on `master`.  That is, `master` is an ancestor, and there are only new
>commits in `my-branch`.  When that happens, Git does what's called a fast-forward
>by default, and simply updates `master` to `my-branch` without even invoking the
>merge algorithm.
>That's why the contents of the branch are those of `my-branch`.
>
>The reason that Git does that is that it's much more efficient and produces the same
>results as actually doing a merge.  When Git does a three-way merge (which is the
>default behaviour), it only really considers three points in the merge: the two heads
>(in this case, `master` and `my-branch`), and the _merge base_, which is usually the
>most recent common ancestor.
>
>When it does a merge, Git determines if there is a change in a particular file between
>the merge base and each of the heads (not considering intermediate commits).  If
>one side has a change and the other does not, Git adopts that change, regardless of
>what happened in in between.  For this reason, you can see that the merge base is
>the old version of `master`, and that's also one of the heads, while the other one is
>`my-branch`.  So one side never has any changes because its the same commit, and
>the other side may have changes or not, so it's safe to just update the branch
>pointer to the new commit.
>
>Note that you can merge with `git merge --no-ff my-branch`, which will do a merge,
>create a merge commit, and avoid the fast forward, but the result is the same, as
>mentioned above.
>
>So I think this is working as intended.

Another option, from my own bag of tricks, is to use git merge --squash for this activity.
This collapses your branch into a single commit and applies it to master. This is done
for simplification of history. It may not be appropriate for everyone (I have a list of
reasons why not, if interested).

Regards,
Randall