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 <sandals@xxxxxxxxxxxxxxxxxxxx> >| Date: Fri Aug 2 19:51:42 2024 +0000 >| >| step 2 >| >* commit a1bf54082762cdcffec185d4cf6eef2c753af535 > Author: brian m. carlson <sandals@xxxxxxxxxxxxxxxxxxxx> > 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