Skip to content

Commit

Permalink
feat(split): extend branch if checked out on split commit
Browse files Browse the repository at this point in the history
  • Loading branch information
claytonrcarter committed Dec 8, 2024
1 parent 55bd028 commit 4ea0c44
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 42 deletions.
84 changes: 57 additions & 27 deletions git-branchless/src/commands/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use eyre::Context;
use rayon::ThreadPoolBuilder;
use std::{
collections::HashMap,
fmt::Write,
path::Path,
time::{SystemTime, UNIX_EPOCH},
Expand Down Expand Up @@ -250,34 +249,65 @@ pub fn split(
event_tx_id,
commit_oid: extracted_commit_oid,
}])?;
move_branches(effects, git_run_info, &repo, event_tx_id, &{
let mut result = HashMap::new();
result.insert(commit_to_split_oid, MaybeZeroOid::NonZero(split_commit_oid));
result
})?;

let head_info = repo.get_head_info()?;
if let ResolvedReferenceInfo {
oid: Some(oid),
reference_name: _,
} = head_info
{
if oid == commit_to_split_oid {
try_exit_code!(check_out_commit(
effects,
git_run_info,
&repo,
&event_log_db,
event_tx_id,
Some(CheckoutTarget::Oid(split_commit_oid)),
&CheckOutCommitOptions {
additional_args: Default::default(),
force_detach: true,
reset: false,
render_smartlog: false,
},
)?);
}
let (checkout_target, rewritten_oids) = match head_info {
// branch @ split commit checked out: extend branch to include extracted
// commit; branch will stay checked out w/ any explicit checkout
ResolvedReferenceInfo {
oid: Some(oid),
reference_name: Some(_),
} if oid == commit_to_split_oid => (
None,
vec![(
commit_to_split_oid,
MaybeZeroOid::NonZero(extracted_commit_oid),
)],
),

// commit to split checked out as detached HEAD, don't extend any
// branches, but explicitly check out the newly split commit
ResolvedReferenceInfo {
oid: Some(oid),
reference_name: None,
} if oid == commit_to_split_oid => (
Some(CheckoutTarget::Oid(split_commit_oid)),
vec![(commit_to_split_oid, MaybeZeroOid::NonZero(split_commit_oid))],
),

// some other commit or branch was checked out, default behavior is fine
ResolvedReferenceInfo {
oid: _,
reference_name: _,
} => (
None,
vec![(commit_to_split_oid, MaybeZeroOid::NonZero(split_commit_oid))],
),
};

move_branches(
effects,
git_run_info,
&repo,
event_tx_id,
&(rewritten_oids.into_iter().collect()),
)?;

if checkout_target.is_some() {
try_exit_code!(check_out_commit(
effects,
git_run_info,
&repo,
&event_log_db,
event_tx_id,
Some(CheckoutTarget::Oid(split_commit_oid)),
&CheckOutCommitOptions {
additional_args: Default::default(),
force_detach: true,
reset: false,
render_smartlog: false,
},
)?);
}

let mut builder = RebasePlanBuilder::new(&dag, permissions);
Expand Down
19 changes: 4 additions & 15 deletions git-branchless/tests/test_split.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::PathBuf;

use lib::testing::{make_git, GitRunOptions};

#[test]
Expand Down Expand Up @@ -364,23 +366,10 @@ fn test_split_attached_branch() -> eyre::Result<()> {
Nothing to restack.
O f777ecc (master) create initial.txt
|
@ 2932db7 (> branch-name) first commit
o 2932db7 first commit
|
o c159d6a temp(split): test2.txt
@ c159d6a (> branch-name) temp(split): test2.txt
"###);
}

{
// TODO confirm that this is correct: the file exists as unstaged & new
// in this commit, but is still part of the next commit Should this
// instead delete the file from working copy and leave it only in the
// extracted commit?
let (stdout, _stderr) = git.run(&["status", "--short"])?;
insta::assert_snapshot!(&stdout, @r#"
A test2.txt
"#);

git.branchless("next", &[])?;

let (stdout, _stderr) = git.run(&["status", "--short"])?;
insta::assert_snapshot!(&stdout, @r#""#);
Expand Down

0 comments on commit 4ea0c44

Please sign in to comment.