arxanas / git-branchless

High-velocity, monorepo-scale workflow for Git
Apache License 2.0
3.46k stars 87 forks source link

Aborting a rebase started by `git sync --merge` then `git undo -i` deletes the main branch #700

Open mlcui-corp opened 1 year ago

mlcui-corp commented 1 year ago

Description of the bug

See command log below:

Command log ``` $ git init sync-abort $ cd sync-abort $ git commit --allow-empty -m "Initial commit" [main (root-commit) 6dfb64b] Initial commit git branchless init Created config file at ~/git/branchless-testing/sync-abort/.git/branchless/config Auto-detected your main branch as: main If this is incorrect, run: git branchless init --main-branch Installing hooks: post-commit, post-merge, post-rewrite, post-checkout, pre-auto-gc, reference-transaction Successfully installed git-branchless. To uninstall, run: git branchless init --uninstall $ git switch --detach branchless: processing 1 update: ref HEAD HEAD is now at 6dfb64b Initial commit branchless: processing checkout $ echo "Hello, world!" > a.txt && git add a.txt && git commit -m "a: Hello, world!" branchless: processing 1 update: ref HEAD branchless: processed commit: e2880de a: Hello, world! [detached HEAD e2880de] a: Hello, world! 1 file changed, 1 insertion(+) create mode 100644 a.txt $ echo "Hello, world!" > b.txt && git add b.txt && git commit -m "b: Hello, world!" branchless: processing 1 update: ref HEAD branchless: processed commit: 5d269df b: Hello, world! [detached HEAD 5d269df] b: Hello, world! 1 file changed, 1 insertion(+) create mode 100644 b.txt $ git switch main Previous HEAD position was 5d269df b: Hello, world! Switched to branch 'main' branchless: processing checkout $ echo "Hello world" | tee a.txt b.txt Hello world $ git add a.txt b.txt && git commit -m "a, b: Hello world" branchless: processing 2 updates: branch main, ref HEAD branchless: processed commit: f9f3612 a, b: Hello world [main f9f3612] a, b: Hello world 2 files changed, 2 insertions(+) create mode 100644 a.txt create mode 100644 b.txt $ git sl ◇ 6dfb64b 9m Initial commit ┣━┓ ┃ ◯ e2880de 2m a: Hello, world! ┃ ┃ ┃ ◯ 5d269df 2m b: Hello, world! ┃ ◆ f9f3612 10s (ᐅ main) a, b: Hello world $ git sync --merge Attempting rebase in-memory... There was a merge conflict, which currently can't be resolved when rebasing in-memory. The conflicting commit was: e2880de a: Hello, world! Trying again on-disk... branchless: running command: git diff --quiet Calling Git for on-disk rebase... branchless: running command: git rebase --continue branchless: processing 1 update: ref HEAD Auto-merging a.txt CONFLICT (add/add): Merge conflict in a.txt error: could not apply e2880de... a: Hello, world! hint: Resolve all conflicts manually, mark them as resolved with hint: "git add/rm ", then run "git rebase --continue". hint: You can instead skip this commit: run "git rebase --skip". hint: To abort and get back to the state before "git rebase", run "git rebase --abort". Could not apply e2880de... # ... resolve merge conflict for this commit... $ git rebase --continue branchless: processing 1 update: ref HEAD branchless: processed commit: ac04bfe a: Hello, world! [detached HEAD ac04bfe] a: Hello, world! 1 file changed, 1 insertion(+), 1 deletion(-) Executing: git branchless hook-detect-empty-commit e2880de6c8c5f980ecf15b604150b1e824537572 Auto-merging b.txt CONFLICT (add/add): Merge conflict in b.txt error: could not apply 5d269df... b: Hello, world! hint: Resolve all conflicts manually, mark them as resolved with hint: "git add/rm ", then run "git rebase --continue". hint: You can instead skip this commit: run "git rebase --skip". hint: To abort and get back to the state before "git rebase", run "git rebase --abort". Could not apply 5d269df... $ git sl ◇ 6dfb64b 11m Initial commit ┣━┓ ┃ ◯ e2880de 5m a: Hello, world! ┃ ┃ ┃ ◯ 5d269df 4m b: Hello, world! ┃ ◇ f9f3612 2m (main) a, b: Hello world ┃ ● ac04bfe 18s a: Hello, world! $ git rebase --abort branchless: processing 1 update: branch main $ git sl ◇ 6dfb64b 11m Initial commit ┣━┓ ┃ ◯ e2880de 5m a: Hello, world! ┃ ┃ ┃ ◯ 5d269df 4m b: Hello, world! ┃ ◆ f9f3612 2m (ᐅ main) a, b: Hello world ┃ ◯ ac04bfe 29s a: Hello, world! # issue: undoing from here results in the main branch being deleted $ git undo -i # choose the smartlog without ac04bfe Will apply these actions: 1. Delete branch main at f9f3612 a, b: Hello world 2. Hide commit ac04bfe a: Hello, world! 3. Check out from ac04bfe a: Hello, world! to f9f3612 a, b: Hello world Confirm? [yN] y branchless: creating working copy snapshot The application panicked (crashed). Message: A fatal error occurred: 0: Updating to previous HEAD location 1: Could not find repository main branch Location: git-branchless-lib/src/core/repo_ext.rs:74 Suggestion: The main branch "main" could not be found in your repository at path: "/usr/local/google/home/mlcui/git/branchless-testing/sync-abort/.git/". These branches exist: [] Either create it, or update the main branch setting by running: git branchless init --main-branch Note that remote main branches are no longer supported as of v0.6.0. See https://github.com/arxanas/git-branchless/discussions/595 for more details. Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it. Run with RUST_BACKTRACE=full to include source snippets. Location: git-branchless/src/commands/mod.rs:468 Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it. Run with RUST_BACKTRACE=full to include source snippets. $ git switch -c main branchless: processing 1 update: branch main Switched to a new branch 'main' branchless: processing checkout $ git branchless bug-report (attached) $ git sl ◇ 6dfb64b 20m Initial commit ┣━┓ ┃ ◯ e2880de 14m a: Hello, world! ┃ ┃ ┃ ◯ 5d269df 13m b: Hello, world! ┃ ◆ f9f3612 11m (ᐅ main) a, b: Hello world ```

I saw that commits created during a reverted rebase remain in the smartlog. This is very minor - users can git hide them, although they aren't marked as successors of the rewritten commits so users will need to resolve the same merge conflict again. This is more of a feature request than a bug report, but can these be marked as a rewrite of the previous commit - so users can continue the sync / restack at a later time?

Expected behavior

Aborting a rebase started by git sync --merge, then doing git undo -i, undos correctly.

Actual behavior

Aborting a rebase started by git sync --merge, then doing git undo -i, deletes the main branch.

Version of rustc

No response

Automated bug report

Software version

git-branchless 0.7.0-pre.1 (v0.3.6-nixos.0-655-gf698e09)

Operating system

Linux 5.19.11-1rodete1-amd64

Command-line

~/.cargo/bin/git-branchless bug-report 

Environment variables

SHELL=/bin/zsh
EDITOR=nvim

Git version

> git version 
git version 2.39.0.rc1.256.g54fd8350bd-goog

Hooks

Show 6 hooks ##### Hook `post-commit` ``` #!/bin/sh ## START BRANCHLESS CONFIG git branchless hook-post-commit "$@" ## END BRANCHLESS CONFIG ``` ##### Hook `post-merge` ``` #!/bin/sh ## START BRANCHLESS CONFIG git branchless hook-post-merge "$@" ## END BRANCHLESS CONFIG ``` ##### Hook `post-rewrite` ``` #!/bin/sh ## START BRANCHLESS CONFIG git branchless hook-post-rewrite "$@" ## END BRANCHLESS CONFIG ``` ##### Hook `post-checkout` ``` #!/bin/sh ## START BRANCHLESS CONFIG git branchless hook-post-checkout "$@" ## END BRANCHLESS CONFIG ``` ##### Hook `pre-auto-gc` ``` #!/bin/sh ## START BRANCHLESS CONFIG git branchless hook-pre-auto-gc "$@" ## END BRANCHLESS CONFIG ``` ##### Hook `reference-transaction` ``` #!/bin/sh ## START BRANCHLESS CONFIG # Avoid canceling the reference transaction in the case that `branchless` fails # for whatever reason. git branchless hook-reference-transaction "$@" || ( echo 'branchless: Failed to process reference transaction!' echo 'branchless: Some events (e.g. branch updates) may have been lost.' echo 'branchless: This is a bug. Please report it.' ) ## END BRANCHLESS CONFIG ```

Events

Show 5 events ##### Event ID: 18, transaction ID: 25 (message: hook-post-checkout) 1. `RefUpdateEvent { timestamp: 1670821239.7127469, event_tx_id: EventTransactionId(25), ref_name: ReferenceName("HEAD"), old_oid: f9f3612960af426ced33ab2eeb2d70124cbceaff, new_oid: f9f3612960af426ced33ab2eeb2d70124cbceaff, message: None }` ``` O 6dfb64b 17m xxxxxxx xxxxxx |\ | o e2880de 11m xx xxxxxx xxxxxx | | | o 5d269df 10m xx xxxxxx xxxxxx | @ f9f3612 8m (> main) xx xx xxxxx xxxxx ``` ##### Event ID: 17, transaction ID: 24 (message: reference-transaction) 1. `RefUpdateEvent { timestamp: 1670821239.6613429, event_tx_id: EventTransactionId(24), ref_name: ReferenceName("refs/heads/main"), old_oid: 0000000000000000000000000000000000000000, new_oid: f9f3612960af426ced33ab2eeb2d70124cbceaff, message: None }` ``` O 6dfb64b 17m xxxxxxx xxxxxx |\ | o e2880de 11m xx xxxxxx xxxxxx | | | o 5d269df 10m xx xxxxxx xxxxxx | @ f9f3612 8m (> main) xx xx xxxxx xxxxx ``` ##### Event ID: 15, transaction ID: 23 (message: undo) 1. `ObsoleteEvent { timestamp: 1670821189.692501, event_tx_id: EventTransactionId(23), commit_oid: NonZeroOid(ac04bfeed238699fa257406f0d91ecf35186e0f5) }` 1. `WorkingCopySnapshot { timestamp: 1670821196.9232357, event_tx_id: EventTransactionId(23), head_oid: f9f3612960af426ced33ab2eeb2d70124cbceaff, commit_oid: NonZeroOid(2f7257f1b9370abf7ee2857fc5b2138fdee14fb7), ref_name: None }` ``` O 6dfb64b 17m xxxxxxx xxxxxx |\ | o e2880de 11m xx xxxxxx xxxxxx | | | o 5d269df 10m xx xxxxxx xxxxxx | @ f9f3612 8m (> main) xx xx xxxxx xxxxx ``` ##### Event ID: 14, transaction ID: 21 (message: reference-transaction) 1. `RefUpdateEvent { timestamp: 1670821073.873817, event_tx_id: EventTransactionId(21), ref_name: ReferenceName("refs/heads/main"), old_oid: 0000000000000000000000000000000000000000, new_oid: f9f3612960af426ced33ab2eeb2d70124cbceaff, message: None }` ``` O 6dfb64b 17m xxxxxxx xxxxxx |\ | o e2880de 11m xx xxxxxx xxxxxx | | | o 5d269df 10m xx xxxxxx xxxxxx | @ f9f3612 8m (> main) xx xx xxxxx xxxxx ``` ##### Event ID: 13, transaction ID: 15 (message: post-commit) 1. `CommitEvent { timestamp: 1670821047.0, event_tx_id: EventTransactionId(15), commit_oid: NonZeroOid(ac04bfeed238699fa257406f0d91ecf35186e0f5) }` ``` O 6dfb64b 17m xxxxxxx xxxxxx |\ | o e2880de 11m xx xxxxxx xxxxxx | | | o 5d269df 10m xx xxxxxx xxxxxx | @ f9f3612 8m (> main) xx xx xxxxx xxxxx ```

Version of git-branchless

5c13964

Version of git

No response

arxanas commented 1 year ago

Oof, it looks like it might be hard to fix this one. I don't really understand why git undo thought it was appropriate to delete the main branch in this case.

I saw that commits created during a reverted rebase remain in the smartlog. This is very minor - users can git hide them, although they aren't marked as successors of the rewritten commits so users will need to resolve the same merge conflict again. This is more of a feature request than a bug report, but can these be marked as a rewrite of the previous commit - so users can continue the sync / restack at a later time?

Re this point, the issue is similar to https://github.com/arxanas/git-branchless/issues/316. There's no post-abort hook, so it would be hard to run any action when a git rebase is aborted, and we don't know what commits have been rewritten into until the end of the rebase when it calls the post-rewrite hook. It would probably be better if we could at least abort the transaction/not register the newly created commits unless the git rebase completes, which would at least ensure that there's only one copy of the same commit in the smartlog as a result.