don't leave repo in an intermediate state if autorebase is interrupted
This commit is contained in:
parent
66db59d11f
commit
359f96fd2d
|
@ -23,10 +23,6 @@ With this graph built up, the tool can:
|
||||||
- Log a simple list of all PRs in the stack (+ dependencies) to stdout.
|
- Log a simple list of all PRs in the stack (+ dependencies) to stdout.
|
||||||
- Automatically update the stack + push after making local changes.
|
- Automatically update the stack + push after making local changes.
|
||||||
|
|
||||||
Some caveats:
|
|
||||||
|
|
||||||
- The `autorebase` command is not entirely idempotent in cases where it doesn't complete fully. In particular, if all local branches are updated but the final push doesn't go through, you can't run the command again without performing a (manual) reset. This happens because the command relies on remote tracking branches as signposts (this is true at the moment, but it's something of an artifical limitation - there's no reason we can't use a custom signpost of some kind to get around this) to make sure we don't cherry-pick too far.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
14
src/git.rs
14
src/git.rs
|
@ -175,7 +175,9 @@ pub async fn perform_rebase(
|
||||||
|
|
||||||
let base = rev_to_commit(&repo, &remote_ref(remote, pr.base()));
|
let base = rev_to_commit(&repo, &remote_ref(remote, pr.base()));
|
||||||
let head = rev_to_commit(&repo, pr.head());
|
let head = rev_to_commit(&repo, pr.head());
|
||||||
|
|
||||||
let mut stop_cherry_pick_at = repo.merge_base(base.id(), head.id()).unwrap();
|
let mut stop_cherry_pick_at = repo.merge_base(base.id(), head.id()).unwrap();
|
||||||
|
let mut update_local_branches_to = vec![];
|
||||||
|
|
||||||
println!("Checking out {:?}", base);
|
println!("Checking out {:?}", base);
|
||||||
checkout_commit(&repo, &base, None);
|
checkout_commit(&repo, &base, None);
|
||||||
|
@ -197,8 +199,10 @@ pub async fn perform_rebase(
|
||||||
// TODO: Skip if remote/<branch> is the same SHA as <branch> (only until the first cherry-pick)
|
// TODO: Skip if remote/<branch> is the same SHA as <branch> (only until the first cherry-pick)
|
||||||
cherry_pick_range(&repo, &mut walk);
|
cherry_pick_range(&repo, &mut walk);
|
||||||
|
|
||||||
// Update local branch so it points to the stack we're building now
|
// Record the commit (in the new stack) that the local branch should now point to.
|
||||||
repo.branch(pr.head(), &head_commit(&repo), true).unwrap();
|
// Actually perform the switch later on in a batch so we don't leave the repo in
|
||||||
|
// a troubled state if this process is interrupted.
|
||||||
|
update_local_branches_to.push((pr.head(), head_commit(&repo)));
|
||||||
|
|
||||||
// Use remote branch as boundary for the next cherry-pick
|
// Use remote branch as boundary for the next cherry-pick
|
||||||
let from = rev_to_commit(&repo, &remote_ref(remote, pr.head()));
|
let from = rev_to_commit(&repo, &remote_ref(remote, pr.head()));
|
||||||
|
@ -221,5 +225,11 @@ pub async fn perform_rebase(
|
||||||
|
|
||||||
command.spawn()?.await?;
|
command.spawn()?.await?;
|
||||||
|
|
||||||
|
println!("\nUpdating local branches so they point to the new stack.\n");
|
||||||
|
for (branch, target) in update_local_branches_to {
|
||||||
|
println!(" + Branch {} now points to {}", branch, target.id());
|
||||||
|
repo.branch(branch, &target, true).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue