Git Mailing List Archive mirror
 help / color / mirror / Atom feed
* git rebase --root bug
@ 2023-05-10 20:08 Christopher Fretz
  2023-05-10 20:35 ` Kristoffer Haugsbakk
  2023-05-11 14:21 ` Phillip Wood
  0 siblings, 2 replies; 7+ messages in thread
From: Christopher Fretz @ 2023-05-10 20:08 UTC (permalink / raw)
  To: git

Thank you for filling out a Git bug report!
Please answer the following questions to help us understand your issue.

What did you do before the bug happened? (Steps to reproduce your issue)
Run an interactive, root, rebase, select one or more commits to edit, and then leave the repo in the rebase state for long
enough that the "onto" commit expires out of the reflog and gets gc'd.

An example set of commands to immediately reproduce the issue can be seen below:
  $ mkdir git_test

  $ cd git_test

  $ git init
  Initialized empty Git repository in /Users/cfretz/working/git_test/.git/

  $ git commit --allow-empty -m 'root commit'
  [master (root-commit) 01edd93] root commit

  $ git rebase -i --root
  Stopped at 01edd93...  root commit # empty
  You can amend the commit now, with

    git commit --amend

  Once you are satisfied with your changes, run

    git rebase --continue

  $ git reflog expire --expire-unreachable=now --all

  $ git gc --prune=now
  Enumerating objects: 2, done.
  Counting objects: 100% (2/2), done.
  Writing objects: 100% (2/2), done.
  Total 2 (delta 0), reused 0 (delta 0), pack-reused 0

  $ git rebase --continue
  fatal: could not parse 10796537ce108c36191d52368250f403afede30b

What did you expect to happen? (Expected behavior)
Git should consider the "onto" commit to be referenced from the ongoing rebase, and refuse to gc it, even during a --root
rebase.

What happened instead? (Actual behavior)
Git gcs the "onto" commit, breaking the ongoing rebase; after this, no rebase commands work, and your only option is git rebase --quit.
The only way I've discovered to fix this without git rebase --quit is running scary commands to manually create a new dummy "onto" commit,
and then overwrite the onto file in the git directory; I'm not confident that this doesn't somehow cause subtle problems that aren't
immediately obvious.

What's different between what you expected and what actually happened?
Git gcs the onto commit and leaves the repo in a broken state. Without manual intervention to fix the .git directory, or hard bailing out of
the rebase, the repository appears broken. A user less familiar with git would likely just delete the repo, reclone, and start entirely from
scratch.

Anything else you want to add:
The way I originally encountered this issue was by leaving a repo in the rebase state for multiple weeks, coming back to the repo to finish the
work, and then having the repo broken by a background gc job. I assume the fundamental problem here is that the "onto" commit during a --root
rebase isn't actually a part of the new history, and is just "synthesized" to remove edge cases, and so git sees it as unreachable during the gc.
From one perspective, it might be argued that this is "expected" behavior given the above, but given the severity of the failure I think this should
be considered a bug, and I think git should just unconditionally consider the "onto" commit as _always_ being reachable; it's not obvious to me why
this wouldn't work. My apologies if this bug has already been fixed in a later version of git. Thanks!

Please review the rest of the bug report below.
You can delete any lines you don't wish to share.


[System Info]
git version:
git version 2.37.3
cpu: x86_64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
uname: Darwin 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023; root:xnu-8792.81.3~2/RELEASE_X86_64 x86_64
compiler info: clang: 13.1.6 (clang-1316.0.21.2.5)
libc info: no libc information available
$SHELL (typically, interactive shell): /bin/zsh


[Enabled Hooks]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git rebase --root bug
  2023-05-10 20:08 git rebase --root bug Christopher Fretz
@ 2023-05-10 20:35 ` Kristoffer Haugsbakk
  2023-05-11  4:07   ` Christopher Fretz
  2023-05-11 14:21 ` Phillip Wood
  1 sibling, 1 reply; 7+ messages in thread
From: Kristoffer Haugsbakk @ 2023-05-10 20:35 UTC (permalink / raw)
  To: Christopher Fretz; +Cc: git

On Wed, May 10, 2023, at 22:08, Christopher Fretz wrote:
> Thank you for filling out a Git bug report!

I get a more generic error:

    $ git rebase --continue
    fatal: No rebase in progress?

[System Info]
git version:
git version 2.40.1
cpu: x86_64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
uname: Linux 5.4.0-148-generic #165~18.04.1-Ubuntu SMP Thu Apr 20 01:14:06 UTC 2023 x86_64
compiler info: gnuc: 7.5
libc info: glibc: 2.27
$SHELL (typically, interactive shell): /bin/bash


[Enabled Hooks]

-- 
Kristoffer Haugsbakk

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git rebase --root bug
  2023-05-10 20:35 ` Kristoffer Haugsbakk
@ 2023-05-11  4:07   ` Christopher Fretz
  0 siblings, 0 replies; 7+ messages in thread
From: Christopher Fretz @ 2023-05-11  4:07 UTC (permalink / raw)
  To: Kristoffer Haugsbakk; +Cc: git

Interestingly, I just tried the same on a personal laptop with a fully up-to-date version of git, and I get a more descriptive error:

$ git rebase --continue
error: invalid onto: ‘bdb3861a5176d64862366d702dd5abd396b18ab4'

Not sure what the cause is for the difference in error messages, we appear to be using the same version, but the issue appears to still be present in the most recent release of git regardless.

[System Info]
git version:
git version 2.40.1
cpu: arm64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
uname: Darwin 22.4.0 Darwin Kernel Version 22.4.0: Mon Mar  6 20:59:28 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T6000 arm64
compiler info: clang: 14.0.3 (clang-1403.0.22.14.1)
libc info: no libc information available
$SHELL (typically, interactive shell): /bin/zsh


[Enabled Hooks]

> On May 10, 2023, at 2:35 PM, Kristoffer Haugsbakk <code@khaugsbakk.name> wrote:
> 
> On Wed, May 10, 2023, at 22:08, Christopher Fretz wrote:
>> Thank you for filling out a Git bug report!
> 
> I get a more generic error:
> 
>    $ git rebase --continue
>    fatal: No rebase in progress?
> 
> [System Info]
> git version:
> git version 2.40.1
> cpu: x86_64
> no commit associated with this build
> sizeof-long: 8
> sizeof-size_t: 8
> shell-path: /bin/sh
> uname: Linux 5.4.0-148-generic #165~18.04.1-Ubuntu SMP Thu Apr 20 01:14:06 UTC 2023 x86_64
> compiler info: gnuc: 7.5
> libc info: glibc: 2.27
> $SHELL (typically, interactive shell): /bin/bash
> 
> 
> [Enabled Hooks]
> 
> -- 
> Kristoffer Haugsbakk


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git rebase --root bug
  2023-05-10 20:08 git rebase --root bug Christopher Fretz
  2023-05-10 20:35 ` Kristoffer Haugsbakk
@ 2023-05-11 14:21 ` Phillip Wood
  2023-05-11 16:16   ` Taylor Blau
  1 sibling, 1 reply; 7+ messages in thread
From: Phillip Wood @ 2023-05-11 14:21 UTC (permalink / raw)
  To: Christopher Fretz, git

Hi Christopher

On 10/05/2023 21:08, Christopher Fretz wrote:
> Thank you for filling out a Git bug report!
> Please answer the following questions to help us understand your issue.
> 
> What did you do before the bug happened? (Steps to reproduce your issue)
> Run an interactive, root, rebase, select one or more commits to edit, and then leave the repo in the rebase state for long
> enough that the "onto" commit expires out of the reflog and gets gc'd.
> 
> An example set of commands to immediately reproduce the issue can be seen below:
>    $ mkdir git_test
> 
>    $ cd git_test
> 
>    $ git init
>    Initialized empty Git repository in /Users/cfretz/working/git_test/.git/
> 
>    $ git commit --allow-empty -m 'root commit'
>    [master (root-commit) 01edd93] root commit
> 
>    $ git rebase -i --root
>    Stopped at 01edd93...  root commit # empty
>    You can amend the commit now, with
> 
>      git commit --amend
> 
>    Once you are satisfied with your changes, run
> 
>      git rebase --continue
> 
>    $ git reflog expire --expire-unreachable=now --all
> 
>    $ git gc --prune=now
>    Enumerating objects: 2, done.
>    Counting objects: 100% (2/2), done.
>    Writing objects: 100% (2/2), done.
>    Total 2 (delta 0), reused 0 (delta 0), pack-reused 0
> 
>    $ git rebase --continue
>    fatal: could not parse 10796537ce108c36191d52368250f403afede30b

The cause of the problem is that --root creates an empty commit (known 
as "squash_onto" in the code) which it uses as the "onto" commit. When 
it picks the first commit in the todo list the "onto" commit is amended 
and so is unreachable when the reflog is expired above. I think the best 
fix would be to stop pretending that we have a real "onto" commit when 
--root is used without --onto and either store "new root" 
.git/rebase-merge/onto or not create that file at all.

Best Wishes

Phillip

> What did you expect to happen? (Expected behavior)
> Git should consider the "onto" commit to be referenced from the ongoing rebase, and refuse to gc it, even during a --root
> rebase.
> 
> What happened instead? (Actual behavior)
> Git gcs the "onto" commit, breaking the ongoing rebase; after this, no rebase commands work, and your only option is git rebase --quit.
> The only way I've discovered to fix this without git rebase --quit is running scary commands to manually create a new dummy "onto" commit,
> and then overwrite the onto file in the git directory; I'm not confident that this doesn't somehow cause subtle problems that aren't
> immediately obvious.
> 
> What's different between what you expected and what actually happened?
> Git gcs the onto commit and leaves the repo in a broken state. Without manual intervention to fix the .git directory, or hard bailing out of
> the rebase, the repository appears broken. A user less familiar with git would likely just delete the repo, reclone, and start entirely from
> scratch.
> 
> Anything else you want to add:
> The way I originally encountered this issue was by leaving a repo in the rebase state for multiple weeks, coming back to the repo to finish the
> work, and then having the repo broken by a background gc job. I assume the fundamental problem here is that the "onto" commit during a --root
> rebase isn't actually a part of the new history, and is just "synthesized" to remove edge cases, and so git sees it as unreachable during the gc.
>  From one perspective, it might be argued that this is "expected" behavior given the above, but given the severity of the failure I think this should
> be considered a bug, and I think git should just unconditionally consider the "onto" commit as _always_ being reachable; it's not obvious to me why
> this wouldn't work. My apologies if this bug has already been fixed in a later version of git. Thanks!
> 
> Please review the rest of the bug report below.
> You can delete any lines you don't wish to share.
> 
> 
> [System Info]
> git version:
> git version 2.37.3
> cpu: x86_64
> no commit associated with this build
> sizeof-long: 8
> sizeof-size_t: 8
> shell-path: /bin/sh
> feature: fsmonitor--daemon
> uname: Darwin 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023; root:xnu-8792.81.3~2/RELEASE_X86_64 x86_64
> compiler info: clang: 13.1.6 (clang-1316.0.21.2.5)
> libc info: no libc information available
> $SHELL (typically, interactive shell): /bin/zsh
> 
> 
> [Enabled Hooks]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git rebase --root bug
  2023-05-11 14:21 ` Phillip Wood
@ 2023-05-11 16:16   ` Taylor Blau
  2023-05-11 19:52     ` Christopher Fretz
  2023-05-12 15:18     ` Phillip Wood
  0 siblings, 2 replies; 7+ messages in thread
From: Taylor Blau @ 2023-05-11 16:16 UTC (permalink / raw)
  To: phillip.wood; +Cc: Christopher Fretz, git

On Thu, May 11, 2023 at 03:21:11PM +0100, Phillip Wood wrote:
> The cause of the problem is that --root creates an empty commit (known as
> "squash_onto" in the code) which it uses as the "onto" commit. When it picks
> the first commit in the todo list the "onto" commit is amended and so is
> unreachable when the reflog is expired above. I think the best fix would be
> to stop pretending that we have a real "onto" commit when --root is used
> without --onto and either store "new root" .git/rebase-merge/onto or not
> create that file at all.

Wouldn't it suffice to consider the squash_onto commit as reachable the
same way we do for `--indexed-objects`?

Thanks,
Taylor

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git rebase --root bug
  2023-05-11 16:16   ` Taylor Blau
@ 2023-05-11 19:52     ` Christopher Fretz
  2023-05-12 15:18     ` Phillip Wood
  1 sibling, 0 replies; 7+ messages in thread
From: Christopher Fretz @ 2023-05-11 19:52 UTC (permalink / raw)
  To: Taylor Blau; +Cc: phillip.wood, git

> Wouldn't it suffice to consider the squash_onto commit as reachable the
> same way we do for `--indexed-objects`?

I think this is essentially what I was imagining, although I don’t know if it’d be considered the cleanest possible approach. I guess I just figured that the logic is already structured such that an empty commit is created to avoid having to add special handling for --root all throughout the rebase operation, and so it’s not such a stretch to then automatically consider that commit as always being reachable.

Rebase could also be reworked to not depend on the squash_onto in the case of a --root rebase, but I imagine this would be a much larger change.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git rebase --root bug
  2023-05-11 16:16   ` Taylor Blau
  2023-05-11 19:52     ` Christopher Fretz
@ 2023-05-12 15:18     ` Phillip Wood
  1 sibling, 0 replies; 7+ messages in thread
From: Phillip Wood @ 2023-05-12 15:18 UTC (permalink / raw)
  To: Taylor Blau, phillip.wood; +Cc: Christopher Fretz, git

Hi Taylor

On 11/05/2023 17:16, Taylor Blau wrote:
> On Thu, May 11, 2023 at 03:21:11PM +0100, Phillip Wood wrote:
>> The cause of the problem is that --root creates an empty commit (known as
>> "squash_onto" in the code) which it uses as the "onto" commit. When it picks
>> the first commit in the todo list the "onto" commit is amended and so is
>> unreachable when the reflog is expired above. I think the best fix would be
>> to stop pretending that we have a real "onto" commit when --root is used
>> without --onto and either store "new root" .git/rebase-merge/onto or not
>> create that file at all.
> 
> Wouldn't it suffice to consider the squash_onto commit as reachable the
> same way we do for `--indexed-objects`?

We could do that rather than clean up the implementation of --root. We 
should definitely consider the commit stored in 
.git/rebase-merge/orig-head to be reachable as the following test fails

diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index ff0afad63e..8ac5e2eec6 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -66,6 +66,19 @@ test_expect_success 'setup' '
  SHELL=
  export SHELL

+test_expect_success 'orig-head is not garbage collected' '
+        git checkout --detach &&
+        test_commit --no-tag x &&
+        (
+                set_fake_editor &&
+                FAKE_LINES="1 edit 2" git rebase -i @~2
+        ) &&
+        git reset @^ &&
+        git reflog expire --expire-unreachable=now &&
+        git gc --prune=now &&
+        git rebase --abort
+'
+
  test_expect_success 'rebase --keep-empty' '
          git checkout -b emptybranch primary &&
          git commit --allow-empty -m "empty" &&

I'm not familiar with the gc code, does it use the --indexed-objects 
option of "git rev-list"?

Best Wishes

Phillip

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-05-12 15:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-10 20:08 git rebase --root bug Christopher Fretz
2023-05-10 20:35 ` Kristoffer Haugsbakk
2023-05-11  4:07   ` Christopher Fretz
2023-05-11 14:21 ` Phillip Wood
2023-05-11 16:16   ` Taylor Blau
2023-05-11 19:52     ` Christopher Fretz
2023-05-12 15:18     ` Phillip Wood

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).