)]}'
{
  "commit": "a562d90a350dcbddc8794809aef9608467022e34",
  "tree": "640f47e62f53ae2923fd8a2e38c71a2a632f673a",
  "parents": [
    "d5663a4b05640a44aa52a0cc32ba6a601d7c9149"
  ],
  "author": {
    "name": "Elijah Newren",
    "email": "newren@gmail.com",
    "time": "Mon Nov 03 18:01:48 2025 +0000"
  },
  "committer": {
    "name": "Junio C Hamano",
    "email": "gitster@pobox.com",
    "time": "Mon Nov 17 14:08:09 2025 -0800"
  },
  "message": "merge-ort: fix failing merges in special corner case\n\nAt GitHub, we had a repository that was triggering\n  git: merge-ort.c:3032: process_renames: Assertion `newinfo \u0026\u0026 !newinfo-\u003emerged.clean` failed.\nduring git replay.\n\nThis sounds similar to the somewhat recent f6ecb603ff8a (merge-ort: fix\ndirectory rename on top of source of other rename/delete, 2025-08-06),\nbut the cause is different.  Unlike that case, there are no\nrename-to-self situations arising in this case, and new to this case it\ncan only be triggered during a replay operation on the 2nd or later\ncommit being replayed, never on the first merge in the sequence.\n\nTo trigger, the repository needs:\n  * an upstream which:\n    * renames a file to a different directory, e.g.\n        old/file -\u003e new/file\n    * leaves other files remaining in the original directory (so that\n      e.g. \"old/\" still exists upstream even though file has been\n      removed from it and placed elsewhere)\n  * a topic branch being rebased where:\n    * a commit in the sequence:\n      * modifies old/file\n    * a subsequent commit in the sequence being replayed:\n      * does NOT touch *anything* under new/\n      * does NOT touch old/file\n      * DOES modify other paths under old/\n      * does NOT have any relevant renames that we need to detect\n        _anywhere_ elsewhere in the tree (meaning this interacts\n        interestingly with both directory renames and cached renames)\n\nIn such a case, the assertion will trigger.  The fix turns out to be\nsurprisingly simple.  I have a very vague recollection that I actually\nconsidered whether to add such an if-check years ago when I added the\nvery similar one for oldinfo in 1b6b902d95a5 (merge-ort:\nprocess_renames() now needs more defensiveness, 2021-01-19), but I think\nI couldn\u0027t figure out a possible way to trigger it and was worried at\nthe time that if I didn\u0027t know how to trigger it then I wasn\u0027t so sure\nthat simply skipping it was correct.  Waiting did give me a chance to\nput more thorough tests and checks into place for the rename-to-self\ncases a few months back, which I might not have found as easily\notherwise.  Anyway, put the check in place now and add a test that\ndemonstrates the fix.\n\nNote that this bug, as demonstrated by the conditions listed above,\nruns at the intersection of relevant renames, trivial directory\nresolutions, and cached renames.  All three of those optimizations are\nones that unfortunately make the code (and testcases!) a bit more\ncomplex, and threading all three makes it a bit more so.  However, the\ntestcase isn\u0027t crazy enough that I\u0027d expect no one to ever hit it in\npractice, and was confused why we didn\u0027t see it before.  After some\ndigging, I discovered that merge.directoryRenames\u003dfalse is a workaround\nto this bug, and GitHub used that setting until recently (it was a\n\"temporary\" match-what-libgit2-does piece of code that lasted years\nlonger than intended).  Since the conditions I gave above for triggering\nthis bug rule out the possibility of there being directory renames, one\nmight assume that it shouldn\u0027t matter whether you try to detect such\nrenames if there aren\u0027t any.  However, due to commit a16e8efe5c2b\n(merge-ort: fix merge.directoryRenames\u003dfalse, 2025-03-13), the heavy\nhammer used there means that merge.directoryRenames\u003dfalse ALSO turns off\nrename caching, which is critical to triggering the bug.  This becomes\na bit more than an aside since...\n\nRe-reading that old commit, a16e8efe5c2b (merge-ort: fix\nmerge.directoryRenames\u003dfalse, 2025-03-13), it appears that the solution\nto this latest bug might have been at least a partial alternative\nsolution to that old commit.  And it may have been an improved\nalternative (or at least help implement one), since it may be able to\navoid the heavy-handed disabling of rename cache.  That might be an\ninteresting future thing to investigate, but is not critical for the\ncurrent fix.  However, since I spent time digging it all up, at least\nleave a small comment tweak breadcrumb to help some future reader\n(myself or others) who wants to dig further to connect the dots a little\nquicker.\n\nSigned-off-by: Elijah Newren \u003cnewren@gmail.com\u003e\nSigned-off-by: Junio C Hamano \u003cgitster@pobox.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "23b55c5b929b223668d8b2ebffe6176d3b110884",
      "old_mode": 33188,
      "old_path": "merge-ort.c",
      "new_id": "a1f3333e44a1ef0b20a2d1798096c06348ad5335",
      "new_mode": 33188,
      "new_path": "merge-ort.c"
    },
    {
      "type": "modify",
      "old_id": "dcb734b10b3e2b8ad490639b2ffe7a6062806efb",
      "old_mode": 33261,
      "old_path": "t/t6429-merge-sequence-rename-caching.sh",
      "new_id": "15dd2d94b75f0af1742622a66660c5c2ca71830e",
      "new_mode": 33261,
      "new_path": "t/t6429-merge-sequence-rename-caching.sh"
    }
  ]
}
