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

feat(sync): resolve revset arguments to their entire stacks #1128

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- (#1129) Added a `--dry-run` option to `git submit` to report what would be submitted without actually doing so.

### Changed

- BREAKING (#1128) Arguments/revsets passed to `git sync` are now resolved to their respective stacks.
- This allows `git sync my-branch` to work as expected, instead of needing to use `git sync 'stack(my-branch)'`. The behavior of `git sync` when called without arguments is not affected by this change. If you rely on the previous behavior, please use `git move -x <commit(s)/revset> -d 'main()'` instead.


## [v0.8.0] - 2023-08-27

### Added
Expand Down
18 changes: 10 additions & 8 deletions git-branchless/src/commands/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,21 @@ use lib::git::{
CategorizedReferenceName, Commit, GitRunInfo, NonZeroOid, Repo, ResolvedReferenceInfo,
};

fn get_stack_roots(dag: &Dag) -> eyre::Result<CommitSet> {
fn get_stack_roots(dag: &Dag, commit_sets: Vec<CommitSet>) -> eyre::Result<CommitSet> {
let draft_commits = dag.query_draft_commits()?;

// FIXME: if two draft roots are ancestors of a single commit (due to a
// merge commit), then the entire unit should be treated as one stack and
// moved together, rather than attempting two separate rebases.
let draft_roots = dag.query_roots(draft_commits.clone())?;
Ok(draft_roots)

if commit_sets.is_empty() {
return Ok(draft_roots);
}

let stack_ancestors = dag.query_range(draft_roots, union_all(&commit_sets))?;
dag.query_roots(stack_ancestors)
.map_err(|err| eyre::eyre!("Could not query DAG for stack roots: {err}"))
}

/// Move all commit stacks on top of the main branch.
Expand Down Expand Up @@ -318,12 +325,7 @@ fn execute_sync_plans(
}
};
let main_branch_oid = repo.get_main_branch_oid()?;
let root_commit_oids = if commit_sets.is_empty() {
get_stack_roots(&dag)?
} else {
dag.query_roots(union_all(&commit_sets))?
};

let root_commit_oids = get_stack_roots(&dag, commit_sets)?;
let root_commits = sorted_commit_set(repo, &dag, &root_commit_oids)?;
let permissions =
match RebasePlanPermissions::verify_rewrite_set(&dag, build_options, &root_commit_oids)? {
Expand Down
16 changes: 11 additions & 5 deletions git-branchless/tests/test_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ fn test_sync_pull() -> eyre::Result<()> {
}

#[test]
fn test_sync_specific_commit() -> eyre::Result<()> {
fn test_sync_stack_from_commit() -> eyre::Result<()> {
let git = make_git()?;

if !git.supports_reference_transactions()? {
Expand All @@ -205,6 +205,7 @@ fn test_sync_specific_commit() -> eyre::Result<()> {
git.commit_file("test2", 2)?;
git.run(&["checkout", "-b", "foo"])?;
git.commit_file("test3", 3)?;
git.commit_file("test3-1", 3)?;
git.run(&["checkout", "-b", "bar", "master"])?;
git.commit_file("test4", 4)?;
git.run(&["checkout", "master"])?;
Expand All @@ -216,7 +217,9 @@ fn test_sync_specific_commit() -> eyre::Result<()> {
:
O 96d1c37 create test2.txt
|\
| o 70deb1e (foo) create test3.txt
| o 70deb1e create test3.txt
| |
| o 10523fe (foo) create test3-1.txt
|\
| o f57e36f (bar) create test4.txt
|
Expand All @@ -228,9 +231,10 @@ fn test_sync_specific_commit() -> eyre::Result<()> {
let (stdout, _stderr) = git.branchless("sync", &["foo"])?;
insta::assert_snapshot!(stdout, @r###"
Attempting rebase in-memory...
[1/1] Committed as: 8e521a1 create test3.txt
[1/2] Committed as: 8e521a1 create test3.txt
[2/2] Committed as: 11bfd99 create test3-1.txt
branchless: processing 1 update: branch foo
branchless: processing 1 rewritten commit
branchless: processing 2 rewritten commits
branchless: running command: <git-executable> checkout master
In-memory rebase succeeded.
Synced 70deb1e create test3.txt
Expand All @@ -247,7 +251,9 @@ fn test_sync_specific_commit() -> eyre::Result<()> {
|
@ d2e18e3 (> master) create test5.txt
|
o 8e521a1 (foo) create test3.txt
o 8e521a1 create test3.txt
|
o 11bfd99 (foo) create test3-1.txt
"###);
}

Expand Down
Loading