{"thread":{"id":"65131","subject":"Crash on git log with -L and -G on file rename","startedAt":"2026-03-03T20:42:25Z","lastAt":"2026-03-04T03:02:07Z","messageCount":4,"participants":["Matthew Hughes","Kristoffer Haugsbakk","Junio C Hamano","Koji Nakamaru"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"537732","messageId":"aac-QdjY1ohAqgw_@desktop","threadId":"65131","inReplyTo":null,"subject":"Crash on git log with -L and -G on file rename","fromName":"Matthew Hughes","fromEmail":"matthewhughes934@gmail.com","sentAt":"2026-03-03T20:42:20Z","receivedAt":"2026-03-03T20:42:25Z","isPatch":false,"sender":{"key":"matthewhughes934@gmail.com","avatar":"https://avatars.githubusercontent.com/u/34972397?v=4"},"body":"Hi,\n\nI hit a crash (assertion error) running `git log` with both `-L` and `-G` under\ncertain conditions. I've created script to reproduce the behaviour in a fresh\ngit repo:\n\n    #!/usr/bin/env bash\n\n    set -o errexit\n\n    git init .\n    # Note: example is .rs file, but it should work with anything that -L understands\n    echo \"fn my_func() {}\" > file.rs\n    # 1. file named 'file.rs'\n    git add file.rs\n    git commit --message 'Add the file'\n\n    # 2. separate branch with the file renamed\n    git checkout -b some-branch\n    git mv file.rs new_file.rs\n    git commit --message 'Move the file'\n\n    git checkout -\n    git commit --allow-empty --message 'Some extra commit so we get a merge commit'\n    # 3. merge: one parent has file.rs, the other has new_file.rs\n    git merge --no-edit some-branch\n\n    # 4. post merge, move the file back\n    git mv new_file.rs file.rs\n    git commit --message 'Move the file back'\n\n    # 5. things go BOOM\n    git log -L:my_func:file.rs -G '.'\n\nI'm not sure if _every_ step in that script is necessary, but it's the simplest\nsetup I could figure out to trigger the crash. Running that script I hit the\nerror:\n\n    git: line-log.c:1056: process_diff_filepair: Assertion `pair->two->oid_valid' failed.\n    Aborted                    (core dumped) git log -L:my_func:file.rs -G '.'\n\nThe backtrace shows that the failed assertion occurs under\n`process_ranges_merge_commit`, so maybe there's an issue with the file being\nrenamed on both sides of the merge?\n\nThe crash requires both flags to trigger, remove either and it will run fine.\n\nI've tested the above on the `git` from my system package manager on Arch\nLinux: git version 2.53.0, and one built from source at\n2cc71917514657b93014134350864f4849edfc83 (the version of 'master' checked out\non my machine at the time). I don't think reproduction relies on any specific\nconfig since I've had it trigger with both `GIT_CONFIG_GLOBAL` and\n`GIT_CONFIG_SYSTEM` set to `/dev/null`\n\nJust for reference, I originally triggered the bug in the `rustfmt` repo[1]\n(checked-out at cebab3e99259be82ff069e5ae89e91855d79e534) running:\n\n    git log -G offset_left -L:format_trait:src/items.rs\n\nLink: github.com/rust-lang/rustfmt [1]\n"},{"id":"537741","messageId":"54a45011-c0f5-4852-b344-b81c36ed8924@app.fastmail.com","threadId":"65131","inReplyTo":"aac-QdjY1ohAqgw_@desktop","subject":"Re: Crash on git log with -L and -G on file rename","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-03-03T23:49:53Z","receivedAt":"2026-03-03T23:50:14Z","isPatch":false,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Tue, Mar 3, 2026, at 21:42, Matthew Hughes wrote:\n> Hi,\n>\n> I hit a crash (assertion error) running `git log` with both `-L` and `-G` under\n> certain conditions. I've created script to reproduce the behaviour in a fresh\n> git repo:\n>\n>     #!/usr/bin/env bash\n>\n>     set -o errexit\n>\n>     git init .\n>     # Note: example is .rs file, but it should work with anything that\n> -L understands\n>     echo \"fn my_func() {}\" > file.rs\n>     # 1. file named 'file.rs'\n>     git add file.rs\n>     git commit --message 'Add the file'\n>\n>     # 2. separate branch with the file renamed\n>     git checkout -b some-branch\n>     git mv file.rs new_file.rs\n>     git commit --message 'Move the file'\n>\n>     git checkout -\n>     git commit --allow-empty --message 'Some extra commit so we get a\n> merge commit'\n>     # 3. merge: one parent has file.rs, the other has new_file.rs\n>     git merge --no-edit some-branch\n>\n>     # 4. post merge, move the file back\n>     git mv new_file.rs file.rs\n>     git commit --message 'Move the file back'\n>\n>     # 5. things go BOOM\n>     git log -L:my_func:file.rs -G '.'\n>\n> I'm not sure if _every_ step in that script is necessary, but it's the simplest\n> setup I could figure out to trigger the crash. Running that script I hit the\n> error:\n>\n>     git: line-log.c:1056: process_diff_filepair: Assertion\n> `pair->two->oid_valid' failed.\n>     Aborted                    (core dumped) git log -L:my_func:file.rs\n> -G '.'\n>\n> The backtrace shows that the failed assertion occurs under\n> `process_ranges_merge_commit`, so maybe there's an issue with the file being\n> renamed on both sides of the merge?\n>\n> The crash requires both flags to trigger, remove either and it will run fine.\n>\n> I've tested the above on the `git` from my system package manager on Arch\n> Linux: git version 2.53.0, and one built from source at\n> 2cc71917514657b93014134350864f4849edfc83 (the version of 'master' checked out\n> on my machine at the time). I don't think reproduction relies on any specific\n> config since I've had it trigger with both `GIT_CONFIG_GLOBAL` and\n> `GIT_CONFIG_SYSTEM` set to `/dev/null`\n>\n> Just for reference, I originally triggered the bug in the `rustfmt` repo[1]\n> (checked-out at cebab3e99259be82ff069e5ae89e91855d79e534) running:\n>\n>     git log -G offset_left -L:format_trait:src/items.rs\n>\n> Link: github.com/rust-lang/rustfmt [1]\n\nI was able to reproduce this on `master`, `next`, and `seen`.\n\n• master: 50d063e3 (The 10th batch, 2026-03-03)\n• seen: 62670724 (Merge branch 'ng/submodule-default-remote' into seen,\n  2026-03-03)\n• 87284122 (Sync with 'master', 2026-03-03)\n"},{"id":"537744","messageId":"xmqqseag9wme.fsf@gitster.g","threadId":"65131","inReplyTo":"54a45011-c0f5-4852-b344-b81c36ed8924@app.fastmail.com","subject":"Re: Crash on git log with -L and -G on file rename","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-04T02:06:17Z","receivedAt":"2026-03-04T02:06:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Kristoffer Haugsbakk\" <kristofferhaugsbakk@fastmail.com> writes:\n\n> I was able to reproduce this on `master`, `next`, and `seen`.\n>\n> • master: 50d063e3 (The 10th batch, 2026-03-03)\n> • seen: 62670724 (Merge branch 'ng/submodule-default-remote' into seen,\n>   2026-03-03)\n> • 87284122 (Sync with 'master', 2026-03-03)\n\nNot surprised, as I do not recall we made any changes to code paths\naround either -L nor -G for quite some time.  I wouldn't be\nsurprised if this were broken exactly the same way since the\ninception of the -L option, but bisecting might shed some lights on\nthe root cause, perhaps?\n\nThanks.\n\n"},{"id":"537745","messageId":"CAOTNsDwdS=+4RuAD6pAt-==uE6S4Wq_4cat+0OqmKV2wgoVheQ@mail.gmail.com","threadId":"65131","inReplyTo":"aac-QdjY1ohAqgw_@desktop","subject":"Re: Crash on git log with -L and -G on file rename","fromName":"Koji Nakamaru","fromEmail":"koji.nakamaru@gree.net","sentAt":"2026-03-04T03:01:54Z","receivedAt":"2026-03-04T03:02:07Z","isPatch":false,"sender":{"key":"koji.nakamaru@gree.net","avatar":"https://avatars.githubusercontent.com/u/2645978?v=4"},"body":"On Wed, Mar 4, 2026 at 5:42 AM Matthew Hughes\n<matthewhughes934@gmail.com> wrote:\n>\n> Hi,\n>\n> I hit a crash (assertion error) running `git log` with both `-L` and `-G` under\n> certain conditions. I've created script to reproduce the behaviour in a fresh\n> git repo:\n>\n>     #!/usr/bin/env bash\n>\n>     set -o errexit\n>\n>     git init .\n>     # Note: example is .rs file, but it should work with anything that -L understands\n>     echo \"fn my_func() {}\" > file.rs\n>     # 1. file named 'file.rs'\n>     git add file.rs\n>     git commit --message 'Add the file'\n>\n>     # 2. separate branch with the file renamed\n>     git checkout -b some-branch\n>     git mv file.rs new_file.rs\n>     git commit --message 'Move the file'\n>\n>     git checkout -\n>     git commit --allow-empty --message 'Some extra commit so we get a merge commit'\n>     # 3. merge: one parent has file.rs, the other has new_file.rs\n>     git merge --no-edit some-branch\n>\n>     # 4. post merge, move the file back\n>     git mv new_file.rs file.rs\n>     git commit --message 'Move the file back'\n>\n>     # 5. things go BOOM\n>     git log -L:my_func:file.rs -G '.'\n>\n> I'm not sure if _every_ step in that script is necessary, but it's the simplest\n> setup I could figure out to trigger the crash. Running that script I hit the\n> error:\n>\n>     git: line-log.c:1056: process_diff_filepair: Assertion `pair->two->oid_valid' failed.\n>     Aborted                    (core dumped) git log -L:my_func:file.rs -G '.'\n>\n> The backtrace shows that the failed assertion occurs under\n> `process_ranges_merge_commit`, so maybe there's an issue with the file being\n> renamed on both sides of the merge?\n>\n> The crash requires both flags to trigger, remove either and it will run fine.\n>\n> I've tested the above on the `git` from my system package manager on Arch\n> Linux: git version 2.53.0, and one built from source at\n> 2cc71917514657b93014134350864f4849edfc83 (the version of 'master' checked out\n> on my machine at the time). I don't think reproduction relies on any specific\n> config since I've had it trigger with both `GIT_CONFIG_GLOBAL` and\n> `GIT_CONFIG_SYSTEM` set to `/dev/null`\n>\n> Just for reference, I originally triggered the bug in the `rustfmt` repo[1]\n> (checked-out at cebab3e99259be82ff069e5ae89e91855d79e534) running:\n>\n>     git log -G offset_left -L:format_trait:src/items.rs\n>\n> Link: github.com/rust-lang/rustfmt [1]\n>\n\nThe root cause appears to be that diff_might_be_rename() only checks\ndiff_queued_diff.queue[i]->one. The following change can fix the issue.\n\ndiff --git a/line-log.c b/line-log.c\nindex eeaf68454e..2da7658ba9 100644\n--- a/line-log.c\n+++ b/line-log.c\n@@ -834,6 +834,10 @@ static inline int diff_might_be_rename(void)\n            /* fprintf(stderr, \"diff_might_be_rename found creation\nof: %s\\n\", */\n            /*  diff_queued_diff.queue[i]->two->path); */\n            return 1;\n+       } else if (!DIFF_FILE_VALID(diff_queued_diff.queue[i]->two)) {\n+           /* fprintf(stderr, \"diff_might_be_rename found deletion\nof: %s\\n\", */\n+           /*  diff_queued_diff.queue[i]->one->path); */\n+           return 1;\n        }\n    return 0;\n }\n\n--\nKoji Nakamaru\n"}]}