{"thread":{"id":"63809","subject":"Possible git bisect behavior issue when skipping commits","startedAt":"2025-07-19T15:31:31Z","lastAt":"2025-07-21T17:03:54Z","messageCount":4,"participants":["Begad Habib","Junio C Hamano","Christian Couder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"522320","messageId":"CACy3CeRjyGb-T=hJURJbXXcR+_KtCsRsMzyw0EvusCZOpWb4Xw@mail.gmail.com","threadId":"63809","inReplyTo":null,"subject":"Possible git bisect behavior issue when skipping commits","fromName":"Begad Habib","fromEmail":"begadhabib989@gmail.com","sentAt":"2025-07-19T15:31:19Z","receivedAt":"2025-07-19T15:31:31Z","isPatch":false,"sender":{"key":"begadhabib989@gmail.com","avatar":null},"body":"Hi Git developers,\n\nI've been analyzing the behavior of `git bisect` when dealing with\nskipped commits and noticed what might be an unexpected result. I\nwanted to share a minimal reproduction to understand whether this is\nintended behavior.\n--\n## Environment\n- Git version: 2.43.0\n- OS: Ubuntu 22.04\n---\n\nSteps to Reproduce\n\n```mkdir bisect-bug-test && cd bisect-bug-test\ngit init\n\n# Commit 1 – good\necho \"good\" > file.txt\ngit add file.txt\ngit commit -m \"Commit 1 - good\"\n\n# Commit 2 – skipped\necho \"middle\" > file.txt\ngit add file.txt\ngit commit -m \"Commit 2 - middle\"\n\n# Commit 3 – bad\necho \"bad\" > file.txt\ngit add file.txt\ngit commit -m \"Commit 3 - bad\"\n\n# Start bisect\ngit bisect start\ngit bisect bad\ngit bisect good HEAD~2\ngit bisect skip HEAD~1\n\n\nObserved Output\n\nThere are only 'skip'ped commits left to test.\nThe first bad commit could be any of:\n<commit 1>\n<commit 2>\nWe cannot bisect more!\n\nThis output is a bit confusing, since the bad commit was already\nidentified (HEAD, i.e., Commit 3), and the middle one was explicitly\nskipped. Including the good commit (Commit 1) in the potential bad\nlist could mislead users into thinking it might be faulty.\n\nQuestion\n\nIs this the expected behavior for skipped commits? Or could the output\nbe more accurate by excluding commits already marked as good?\n\nThanks for your time and the amazing work you all do on Git 🙏\nBest regards\n"},{"id":"522331","messageId":"xmqqwm83zmuk.fsf@gitster.g","threadId":"63809","inReplyTo":"CACy3CeRjyGb-T=hJURJbXXcR+_KtCsRsMzyw0EvusCZOpWb4Xw@mail.gmail.com","subject":"Re: Possible git bisect behavior issue when skipping commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-07-20T01:12:51Z","receivedAt":"2025-07-20T01:12:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Begad Habib <begadhabib989@gmail.com> writes:\n\n> Hi Git developers,\n>\n> I've been analyzing the behavior of `git bisect` when dealing with\n> skipped commits and noticed what might be an unexpected result. I\n> wanted to share a minimal reproduction to understand whether this is\n> intended behavior.\n> --\n> ## Environment\n> - Git version: 2.43.0\n> - OS: Ubuntu 22.04\n> ---\n\nThanks for a report.\n\nCC'ing the primary author of \"git bisect skip\" and showing of\nskipped ones for their thoughts.\n\n> Steps to Reproduce\n>\n> ```mkdir bisect-bug-test && cd bisect-bug-test\n> git init\n>\n> # Commit 1 – good\n> echo \"good\" > file.txt\n> git add file.txt\n> git commit -m \"Commit 1 - good\"\n>\n> # Commit 2 – skipped\n> echo \"middle\" > file.txt\n> git add file.txt\n> git commit -m \"Commit 2 - middle\"\n>\n> # Commit 3 – bad\n> echo \"bad\" > file.txt\n> git add file.txt\n> git commit -m \"Commit 3 - bad\"\n>\n> # Start bisect\n> git bisect start\n> git bisect bad\n> git bisect good HEAD~2\n> git bisect skip HEAD~1\n>\n>\n> Observed Output\n>\n> There are only 'skip'ped commits left to test.\n> The first bad commit could be any of:\n> <commit 1>\n> <commit 2>\n> We cannot bisect more!\n>\n> This output is a bit confusing, since the bad commit was already\n> identified (HEAD, i.e., Commit 3), and the middle one was explicitly\n> skipped. Including the good commit (Commit 1) in the potential bad\n> list could mislead users into thinking it might be faulty.\n>\n> Question\n>\n> Is this the expected behavior for skipped commits? Or could the output\n> be more accurate by excluding commits already marked as good?\n>\n> Thanks for your time and the amazing work you all do on Git 🙏\n> Best regards\n"},{"id":"522335","messageId":"CAP8UFD1bwe92zbXHWe-LiMSJZtcTJQwi9mtgNCm-_kTeyFk08w@mail.gmail.com","threadId":"63809","inReplyTo":"CACy3CeRjyGb-T=hJURJbXXcR+_KtCsRsMzyw0EvusCZOpWb4Xw@mail.gmail.com","subject":"Re: Possible git bisect behavior issue when skipping commits","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2025-07-20T08:34:12Z","receivedAt":"2025-07-20T08:34:27Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Hi,\n\nOn Sat, Jul 19, 2025 at 5:32 PM Begad Habib <begadhabib989@gmail.com> wrote:\n>\n> Hi Git developers,\n>\n> I've been analyzing the behavior of `git bisect` when dealing with\n> skipped commits and noticed what might be an unexpected result. I\n> wanted to share a minimal reproduction to understand whether this is\n> intended behavior.\n> --\n> ## Environment\n> - Git version: 2.43.0\n> - OS: Ubuntu 22.04\n> ---\n>\n> Steps to Reproduce\n>\n> ```mkdir bisect-bug-test && cd bisect-bug-test\n> git init\n>\n> # Commit 1 – good\n> echo \"good\" > file.txt\n> git add file.txt\n> git commit -m \"Commit 1 - good\"\n>\n> # Commit 2 – skipped\n> echo \"middle\" > file.txt\n> git add file.txt\n> git commit -m \"Commit 2 - middle\"\n>\n> # Commit 3 – bad\n> echo \"bad\" > file.txt\n> git add file.txt\n> git commit -m \"Commit 3 - bad\"\n>\n> # Start bisect\n> git bisect start\n> git bisect bad\n> git bisect good HEAD~2\n\nWhen both one \"good\" and one \"bad\" commits have been specified, then\nGit starts bisecting, which means that you should then see something\nlike:\n\nBisecting: 0 revisions left to test after this (roughly 0 steps)\n[df357f37981b7f1e804684cc09842d02fd012146] Commit 2 - middle\n\nand Git should have checked out \"Commit 2 - middle\", so HEAD should\npoint to that commit.\n\nBy the way it could help if you could show git's output when giving\nsteps to reproduce like this.\n\n> git bisect skip HEAD~1\n\nThis will \"skip\" the commit before the current one, so \"Commit 1 -\ngood\", which is already marked as \"good\".\n\nI guess this is not what you want. You wanted to skip \"Commit 2 -\nmiddle\", right? In this case `git bisect skip` (without any additional\nargument) to skip the current commit is enough.\n\n> Observed Output\n\n(Note that I see the output you show below only when \"Commit 2 -\nmiddle\" is skipped by the previous command above.)\n\n> There are only 'skip'ped commits left to test.\n> The first bad commit could be any of:\n> <commit 1>\n> <commit 2>\n\nI am not sure if <commit 1> and <commit 2> here refer to \"Commit 1 -\ngood\" and \"Commit 2 - middle\" respectively or not. To avoid confusion,\nyou might want to be explicit about what they refer to.\n\nAnyway when I try to reproduce, I see the hashes of \"Commit 2 -\nmiddle\" and \"Commit 3 - bad\" which is what I expected.\n\n> We cannot bisect more!\n>\n> This output is a bit confusing, since the bad commit was already\n> identified (HEAD, i.e., Commit 3),\n\nGit's output talks about the \"first bad commit\" not the commit\ncurrently marked as \"bad\". \"first bad commit\" has a special meaning.\nIt means the first commit in the commit history that would be \"bad\" if\nall the commits could be tested (and thus no commit was skipped).\n\n> and the middle one was explicitly\n> skipped.\n\nYeah, but that doesn't mean it couldn't be the \"first bad commit\". The\ngit bisect documentation about \"skip\" says:\n\n\"However, if you skip a commit adjacent to the one you are looking\nfor, Git will be unable to tell exactly which of those commits was the\nfirst bad one.\"\n\nThis is what happens here, and that should be expected. Git cannot\ntell between \"Commit 2 - middle\" and \"Commit 3 - bad\" which one would\nbe the first bad one if all the commits could be tested.\n\n> Including the good commit (Commit 1) in the potential bad\n> list could mislead users into thinking it might be faulty.\n\nThat's not what I see. I don't see the hash of \"Commit 1 - good\"\nlisted there when I try to reproduce. But again your reproduction\nsteps have some issues, see above. So I am not sure I reproduced the\nissue you saw or not.\n\n> Question\n>\n> Is this the expected behavior for skipped commits? Or could the output\n> be more accurate by excluding commits already marked as good?\n\nCommits already marked good should be excluded but maybe if you mark\nthem as both \"good\" and \"skip\"ped there could be some issues. Anyway\nwe would need better reproduction steps to be able to debug this. And\nyeah I also tried to mark both \"Commit 1 - good\" and \"Commit 2 -\nmiddle\" as \"skip\"ped, and `git bisect` still seems to work correctly\nto me, especially it still say that it cannot tell between \"Commit 2 -\nmiddle\" and \"Commit 3 - bad\" (without showing the hash of \"Commit 1 -\ngood\").\n\n>  Thanks for your time and the amazing work you all do on Git 🙏\n\nThanks for the kind words!\n"},{"id":"522364","messageId":"xmqqa54xzdaf.fsf@gitster.g","threadId":"63809","inReplyTo":"CAP8UFD1bwe92zbXHWe-LiMSJZtcTJQwi9mtgNCm-_kTeyFk08w@mail.gmail.com","subject":"Re: Possible git bisect behavior issue when skipping commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-07-21T17:03:52Z","receivedAt":"2025-07-21T17:03:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Christian Couder <christian.couder@gmail.com> writes:\n\n>> # Commit 1 – good\n>> echo \"good\" > file.txt\n>> git add file.txt\n>> git commit -m \"Commit 1 - good\"\n>>\n>> # Commit 2 – skipped\n>> echo \"middle\" > file.txt\n>> git add file.txt\n>> git commit -m \"Commit 2 - middle\"\n>>\n>> # Commit 3 – bad\n>> echo \"bad\" > file.txt\n>> git add file.txt\n>> git commit -m \"Commit 3 - bad\"\n>>\n>> # Start bisect\n>> git bisect start\n>> git bisect bad\n>> git bisect good HEAD~2\n>\n> When both one \"good\" and one \"bad\" commits have been specified, then\n> Git starts bisecting, which means that you should then see something\n> like:\n>\n> Bisecting: 0 revisions left to test after this (roughly 0 steps)\n> [df357f37981b7f1e804684cc09842d02fd012146] Commit 2 - middle\n>\n> and Git should have checked out \"Commit 2 - middle\", so HEAD should\n> point to that commit.\n>\n> By the way it could help if you could show git's output when giving\n> steps to reproduce like this.\n>\n>> git bisect skip HEAD~1\n>\n> This will \"skip\" the commit before the current one, so \"Commit 1 -\n> good\", which is already marked as \"good\".\n\nGood eyes.  I missed that \"HEAD~1 no longer means the second one at\nthat point because you gave both bad and good already\", which you\ncorrectly identified as the root cause of the confusion.  The user\nthought #2 is marked to be skipped, but in reality #1 that is good\nis marked for skipping, which would result in nonsensical output, as\nthe final output phase assumes that all skipped ones haven't been\neven tested.\n\nAvoid this (I am not saying we should implement such a safety\nmeasure, at least not yet) would involve \"Are you sure?  You've\nalready said X is A but now you are saying it is B\" confirmation\nwhen \"git bisect {good,bad,skip}\" is used on a commit that the user\nalready said something about.  Allowing them to change their mind is\na good feature.  We'd need to make consistent changes.  For example,\nwhen we create refs/bisect/bad, we should check if we already have\nrefs/bisect/good-* that points at the same commit (and vice versa)\nto make sure we do not mark the same commit as both good and bad.\nThe same thing can be said about \"refs/bisect/skip-*\".\n\nThis is a tangent, but do we forbid using the word \"skip\" as a\ncustomized term for \"good\"?  If we are not, we probably should.\n\nThanks.\n\n\n\n"}]}