Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(#1088) post-rewrite hook does not track intermediate commits from an interactive rebase #1098

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

cshinaver
Copy link

@cshinaver cshinaver commented Oct 12, 2023

Fixes #1088

I was able to repro the issue from #1088. It seems that we are tracking the intermediate commits created by a rebase and adding them to the events db during the post rewrite hook. I noticed that this code was added to prevent aborted rebases from adding intermediate commits, but the test written for that still passes. Looking for feedback on the approach from @arxanas regarding omitting deferred commits from the event log during the post-rewrite hook.

@cshinaver cshinaver force-pushed the cs-1088 branch 4 times, most recently from 7ab7c72 to 7c75b50 Compare October 12, 2023 19:49
@cshinaver
Copy link
Author

The test that is failing is doing a commit in the middle of a rebase. The code I removed is meant to preserve commits done in the middle of the rebase. is this intentional? The final commits should be reserved, but if we want to track the intermediate commits, then all of git's automatically created intermediate commits are also tracked (#1088 )

Copy link
Owner

@arxanas arxanas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this! It's been a thorn in many people's sides for a while.

I noticed that this code was added to prevent aborted rebases from adding intermediate commits, but the test written for that still passes

It looks like the test test_rebase_no_process_new_commits_until_conclusion is failing in CI. Unfortunately, due to bad reasons, you might have to run cargo build --workspace after your change and then run tests (related to https://github.com/arxanas/git-branchless/wiki/Runbook#testing-subcommands-in-isolation). You should also make sure that you're testing with a recent version of Git, as the test body is gated behind Git::supports_reference_transactions.

The final commits should be reserved, but if we want to track the intermediate commits, then all of git's automatically created intermediate commits are also tracked

I think it's okay to not preserve intermediate commits directly as long as 1) the final commits are preserved and 2) aborting the rebase does not preserve the final commits. There may have been a workflow where one uses edit and creates new commits during a rebase, which, in principle, should be tracked, but I am willing to sacrifice that workflow if necessary to support the fixup workflow.

I suspect (but haven't investigated) that the fixup rebase command in Git does not register the fixed-up commits to be emitted as part of the post-rewrite hook, so, as far as git-branchless knows, they're legitimate commits. If so, then, in principle, it would be good to upstream a fix for that to Git, but it wouldn't solve most of our users' fixup problems for a long while.

I would be willing to accept some kind of hack/workaround for fixup specifically, like maybe ignoring commits whose commit messages start with # (which it looks like interactive fixup commits do, but not sure about fixup! with git rebase --autosquash). Another idea is that, during the post-commit hook, you could check the current status of the rebase and see if the most recent command was a fixup, although I'm not sure how feasible it is.

@cshinaver
Copy link
Author

In the failing test, a commit (test 4) is added in the middle of the rebase. In my change, this commit is ignored. Given that you mentioned you would be okay sacrificing the commit in middle of rebase workflow, I'll update the unit test to not commit in the middle of the rebase.

Copy link
Owner

@arxanas arxanas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I think the approach/tests are good; we should just try to not expand the testing API surface unless necessary. (It's already bigger than it should be — for example, practically none of the tests actually need to set a timestamp explicitly, and it's just convention by now...)

@@ -498,14 +498,15 @@ then you can only run tests in the main `git-branchless` and \
/// used to set the commit timestamp, which is factored into the commit
/// hash. The filename is always appended to the message prefix.
#[instrument]
pub fn commit_file_with_contents_and_message(
pub fn commit_file_with_contents_and_message_and_file_name(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather keep the API smaller. Can you revert this change and call write_file followed by commit_file instead? (Or feel free to use git.run(&["commit", ...]); the timestamp should still be stable for tests.)

@@ -148,19 +133,6 @@ pub fn hook_post_rewrite(
let event_log_db = EventLogDb::new(&conn)?;
let event_tx_id = event_log_db.make_transaction_id(now, "hook-post-rewrite")?;

{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there code that also writes the deferred commits that is now also obsolete? If so, we should delete it too. Or, alternatively, keep all the code but comment out the add_events line with a note, as we might need similar code in the future to fix certain other bugs.

Comment on lines +421 to +429
run_in_pty_with_command(
&git,
&["rebase"],
&["-i", "--autosquash", "master"],
&[
PtyAction::WaitUntilContains(" "),
PtyAction::Write(CARRIAGE_RETURN),
],
)?;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just write git.run(&["rebase", "--autosquash", "master"])? It seems to work in my testing. If so, do that and revert the changes to run_in_pty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

git rebase -i "fixup" strands a bunch of commits after squashing
2 participants