git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Matt Neuburg <matt@tidbits.com>
To: git@vger.kernel.org
Subject: possible bug due to directory rename detection
Date: Thu, 15 Apr 2021 12:17:14 +1200	[thread overview]
Message-ID: <C0E64A34-AAA0-4ECE-8EC5-045815B3413D@tidbits.com> (raw)

git version 2.24.3 (Apple Git-128) running under Big Sur on a MacBook Pro.

Please see

  https://stackoverflow.com/questions/67067686/git-file-level-merge-conflict-caused-by-git-suggesting-the-file-should-perhap 

for a complete description of what I saw and why I think it's wrong.

However, I will also reproduce the question here (just copy and paste, in GitHub Markdown format). Notice that I provide a complete `ls` for both branch tips and their merge-base, and since the problem has to do with a file-level merge conflict that I contend is generated by Git itself due to its overly aggressive directory rename detection behavior, that should be sufficient to describe the entire matter.

As I say in a comment on SO:

`git diff --find-renames` from merge-base to master reveals that (as one can also see by eye) the vast preponderance is entirely new stuff in _wordpressed_ or stuff that was moved (renamed) from top level to _wordpressed_. There is exactly one existing rename where an article was moved from _dan_ to _wordpressed_: 

    diff --git a/dan/bdd.md b/wordpressed/bdd.md

And yet on just that basis alone, Git assumes that this new article that popped up in _dan_ should have popped up in _wordpressed_ instead?? I'm sorry, I regard this as a Git bug. There needs at the very least to be a way to turn off this "feature", surely.

Thanks for listening. m.  

========

I've got a Git repo of Markdown articles, where people create pull requests (one per Markdown article) that eventually get merged to `master` and then, working directly on `master`, I move that article into a folder called _wordpressed_ and commit and push to `master`.

And I've got a very old pull request that is still sitting there in a branch called `home-base`, consisting of a file _dan/homebase.md_ which I'm thinking of editing into shape with some more commits and then merging to `master`.

This `home-base` branch is _so_ old that the repo, seen from its point of view, is totally different from how it looks today in `master`. So I thought it might be good to reverse merge `master` into `home-base` just to bring it more up to date and move the merge base up a lot.

But when I try to do that, I get a merge conflict that I can't understand.

----

To show you the situation, I'm going to show what a `ls` of files and folders looks like in each branch. I'll start with `master`:

```
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean

$ ls -1 -R
README.md
dan
instructions.md
wordpressed

./dan:

./wordpressed:
AppDelegateRefactor.md
BareListContentView.md
CellContentConfiguration.md
ControlTargetActioniOS14.md
GetStartedWithPods.md
MultipleTrailingClosures.md
StatesAndBackgrounds.md
Swift52notes1.md
Swift52notes2.md
Swift52notes3.md
UserInteractiveCells.md
bdd-common-pitfalls.md
bdd.md
brantsMenuBar.md
collectionViewContentConfig.md
collectionViewLists.md
collectionViewLists2.md
collectionViewOutline.md
debuggingLinks.md
diffableDataSources.md
diffableDataSources2.md
forwardCompatibity.md
haptics.md
iOS13deprecations.md
images
inAppPurchases.md
logging.md
miscSwiftTricks1.md
miscSwiftTricks2.md
miscSwiftTricks3.md
miscSwiftTricks4.md
multipleSelection.md
mysteriesOfLayout.md
newInIOS14.md
packages.md
photoPicker.md
protocolParadox.md
splitViewControllers.md
splitViewControllers2.md
swiftTrickTwoClasses.md
targetActionRant.md
typescript-shape-of-things.md
untappableButton.md
what-vs-how.md
xcode12Editing.md
xcode12testing.md
xcodeWhereAmI.md
xcodeWorkInTwoPlaces.md

./wordpressed/images:
argumentsInScheme.png
bigFlags.png
callHierarchy.png
callersMenu.png
chooser.png
config.png
createdTester.png
dataOrUrl.png
ipadportraitoverlay.png
listOfPepBoys.png
listWithSectionHeaders.png
littleFlags.png
looksLikeADuck.png
newTester.png
outlineIndicatorsWrong.png
outlineIndicatorsWrong2.png
perfectAfterHack.png
pickAPeppa.png
rootOnly.png
sandboxAccountOnDevice.png
selfSizingStringDrawer.png
simpleList.png
split1.png
split2.png
splitViewControllerPadLandscape.png
tableViewAsChoice.png
threecolumns.png
twoPossibilities.png
twoscreensphone.png
variableRowHeights.png
workingOutline.png
```

As you can see, the main folder is itself mostly empty. All the articles are in _wordpressed_, along with their images which are in _wordpressed/images_.

----

Okay, now here is `home-base`:

```
$ git switch home-base
Switched to branch 'home-base'
Your branch is up to date with 'origin/home-base'.

$ ls -1 -R
GetStartedWithPods.md
README.md
Swift52notes1.md
Swift52notes2.md
Swift52notes3.md
dan
debuggingLinks.md
images
logging.md
miscSwiftTricks1.md
miscSwiftTricks2.md
miscSwiftTricks3.md
miscSwiftTricks4.md
packages.md
wordpressed
xcode12Editing.md
xcode12testing.md
xcodeWhereAmI.md
xcodeWorkInTwoPlaces.md

./dan:
bdd.md
homebase.md

./images:
chooser.png
config.png
split1.png
split2.png

./wordpressed:
images

./wordpressed/images:
```

As you can see, that's a much earlier situation. Nothing had been moved to _wordpressed_ yet. There were a few articles floating around the top level, and the _dan_ folder had two articles, including the one I'm interested in here, _homebase.md_.

----

Finally, for the sake of completeness, I'm going to show you the merge base between `master` and `home-base`:

```
$ git merge-base master home-base
b5d7355fe42eddad96beb200df2cba65381c288a
$ git checkout b5d7355fe
$ ls -1 -R
GetStartedWithPods.md
README.md
Swift52notes1.md
Swift52notes2.md
Swift52notes3.md
dan
debuggingLinks.md
images
logging.md
miscSwiftTricks1.md
miscSwiftTricks2.md
miscSwiftTricks3.md
miscSwiftTricks4.md
packages.md
wordpressed
xcode12Editing.md
xcode12testing.md
xcodeWhereAmI.md
xcodeWorkInTwoPlaces.md

./dan:
bdd.md

./images:
chooser.png
config.png
split1.png
split2.png

./wordpressed:
images

./wordpressed/images:
```

Well, it looks an awful lot like `home-base` looks now, doesn't it? The main difference is that that's before _homebase.md_ appeared in the _dan_ folder.

----

Now then. Ask yourself, please, what should happen when I try to merge `master` into `home-base`. What are contributions from both sides of the merge? In my view, Git should realize that in `master` a lot of new files appeared in _wordpressed_, and that some of them are renames of files that used to be at the top level. Plus, of course, in `home-base`, a new file _homebase.md_ has appeared in _dan_.

Those contributions should not conflict (in my view).

Okay, let's try it.

```
$ git switch home-base
$ git merge master
CONFLICT (file location): dan/homebase.md added in HEAD inside a directory that was renamed in master, suggesting it should perhaps be moved to wordpressed/homebase.md.
Automatic merge failed; fix conflicts and then commit the result.

$ git status
On branch home-base
Your branch is up to date with 'origin/home-base'.

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Changes to be committed:
	deleted:    dan/homebase.md
	new file:   instructions.md
	new file:   wordpressed/AppDelegateRefactor.md
	new file:   wordpressed/BareListContentView.md
	new file:   wordpressed/CellContentConfiguration.md
	new file:   wordpressed/ControlTargetActioniOS14.md
	renamed:    GetStartedWithPods.md -> wordpressed/GetStartedWithPods.md
	new file:   wordpressed/MultipleTrailingClosures.md
	new file:   wordpressed/StatesAndBackgrounds.md
	renamed:    Swift52notes1.md -> wordpressed/Swift52notes1.md
	renamed:    Swift52notes2.md -> wordpressed/Swift52notes2.md
	renamed:    Swift52notes3.md -> wordpressed/Swift52notes3.md
	new file:   wordpressed/UserInteractiveCells.md
	new file:   wordpressed/bdd-common-pitfalls.md
	renamed:    dan/bdd.md -> wordpressed/bdd.md
	new file:   wordpressed/brantsMenuBar.md
	new file:   wordpressed/collectionViewContentConfig.md
	new file:   wordpressed/collectionViewLists.md
	new file:   wordpressed/collectionViewLists2.md
	new file:   wordpressed/collectionViewOutline.md
	renamed:    debuggingLinks.md -> wordpressed/debuggingLinks.md
	new file:   wordpressed/diffableDataSources.md
	new file:   wordpressed/diffableDataSources2.md
	new file:   wordpressed/forwardCompatibity.md
	new file:   wordpressed/haptics.md
	new file:   wordpressed/iOS13deprecations.md
	new file:   wordpressed/images/argumentsInScheme.png
	new file:   wordpressed/images/bigFlags.png
	new file:   wordpressed/images/callHierarchy.png
	new file:   wordpressed/images/callersMenu.png
	renamed:    images/chooser.png -> wordpressed/images/chooser.png
	renamed:    images/config.png -> wordpressed/images/config.png
	new file:   wordpressed/images/createdTester.png
	new file:   wordpressed/images/dataOrUrl.png
	new file:   wordpressed/images/ipadportraitoverlay.png
	new file:   wordpressed/images/listOfPepBoys.png
	new file:   wordpressed/images/listWithSectionHeaders.png
	new file:   wordpressed/images/littleFlags.png
	new file:   wordpressed/images/looksLikeADuck.png
	new file:   wordpressed/images/newTester.png
	new file:   wordpressed/images/outlineIndicatorsWrong.png
	new file:   wordpressed/images/outlineIndicatorsWrong2.png
	new file:   wordpressed/images/perfectAfterHack.png
	new file:   wordpressed/images/pickAPeppa.png
	new file:   wordpressed/images/rootOnly.png
	new file:   wordpressed/images/sandboxAccountOnDevice.png
	new file:   wordpressed/images/selfSizingStringDrawer.png
	new file:   wordpressed/images/simpleList.png
	renamed:    images/split1.png -> wordpressed/images/split1.png
	renamed:    images/split2.png -> wordpressed/images/split2.png
	new file:   wordpressed/images/splitViewControllerPadLandscape.png
	new file:   wordpressed/images/tableViewAsChoice.png
	new file:   wordpressed/images/threecolumns.png
	new file:   wordpressed/images/twoPossibilities.png
	new file:   wordpressed/images/twoscreensphone.png
	new file:   wordpressed/images/variableRowHeights.png
	new file:   wordpressed/images/workingOutline.png
	new file:   wordpressed/inAppPurchases.md
	renamed:    logging.md -> wordpressed/logging.md
	renamed:    miscSwiftTricks1.md -> wordpressed/miscSwiftTricks1.md
	renamed:    miscSwiftTricks2.md -> wordpressed/miscSwiftTricks2.md
	renamed:    miscSwiftTricks3.md -> wordpressed/miscSwiftTricks3.md
	renamed:    miscSwiftTricks4.md -> wordpressed/miscSwiftTricks4.md
	new file:   wordpressed/multipleSelection.md
	new file:   wordpressed/mysteriesOfLayout.md
	new file:   wordpressed/newInIOS14.md
	renamed:    packages.md -> wordpressed/packages.md
	new file:   wordpressed/photoPicker.md
	new file:   wordpressed/protocolParadox.md
	new file:   wordpressed/splitViewControllers.md
	new file:   wordpressed/splitViewControllers2.md
	new file:   wordpressed/swiftTrickTwoClasses.md
	new file:   wordpressed/targetActionRant.md
	new file:   wordpressed/typescript-shape-of-things.md
	new file:   wordpressed/untappableButton.md
	new file:   wordpressed/what-vs-how.md
	renamed:    xcode12Editing.md -> wordpressed/xcode12Editing.md
	renamed:    xcode12testing.md -> wordpressed/xcode12testing.md
	renamed:    xcodeWhereAmI.md -> wordpressed/xcodeWhereAmI.md
	renamed:    xcodeWorkInTwoPlaces.md -> wordpressed/xcodeWorkInTwoPlaces.md

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	added by us:     wordpressed/homebase.md 
```

----

Okay, so that last line is the one I don't understand. What does it mean to say that "added by us" is _wordpressed/homebase.md_? _NO!_ That's not where we added it. We added it in _dan_.

Neither `master` nor `home-base` has a file _wordpressed/homebase.md_. So where is Git getting the idea that there is one??? It seems to have something to do with the same reason why it thinks there is a merge conflict at all:

> _dan/homebase.md_ added in HEAD inside a directory that was renamed in master, suggesting it should perhaps be moved to wordpressed/homebase.md.

So: _What is Git talking about here?_ Why does Git think that _dan/homebase.md_ should be _wordpressed/homebase.md_, on no evidence whatever that I can find? How can I prevent this merge conflict and get Git to be more simplistic about this? Could I perhaps use a different merge strategy? Or how can I simply resolve the conflict in such a way as to say, No, Git, just leave _dan/homebase.md_ alone, please?

Again, apologies for the length of the detail in the question.

========


--
matt neuburg, phd = http://www.apeth.net/matt/
pantes anthropoi tou eidenai oregontai phusei
Programming iOS 14! https://www.oreilly.com/library/view/programming-ios-14/9781492092162/
iOS 14 Fundamentals! https://www.oreilly.com/library/view/ios-14-programming/9781492092087/
RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html


             reply	other threads:[~2021-04-15  0:16 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-15  0:17 Matt Neuburg [this message]
2021-04-15  4:21 ` possible bug due to directory rename detection Elijah Newren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=C0E64A34-AAA0-4ECE-8EC5-045815B3413D@tidbits.com \
    --to=matt@tidbits.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).