From 7ee47064c4fd94e6660e90c664cea7594ab2b9a7 Mon Sep 17 00:00:00 2001 From: Marcel Gotsch Date: Sun, 1 Feb 2026 14:54:22 +0100 Subject: [PATCH] feat: ability to specify the starting point of a new branch Checking out a new branch will first ask for the starting point, defaulting to the current branch. Only after it will ask for the name of the new branch. --- src/ops/branch.rs | 23 ++++++++++++++--- src/tests/branch.rs | 7 +++++- ...u__tests__branch__checkout_new_branch.snap | 4 +-- ...anch__checkout_new_branch_start_point.snap | 25 +++++++++++++++++++ 4 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 src/tests/snapshots/gitu__tests__branch__checkout_new_branch_start_point.snap diff --git a/src/ops/branch.rs b/src/ops/branch.rs index 825234982d..46df5b4fdf 100644 --- a/src/ops/branch.rs +++ b/src/ops/branch.rs @@ -53,15 +53,25 @@ pub(crate) struct CheckoutNewBranch; impl OpTrait for CheckoutNewBranch { fn get_action(&self, _target: &ItemData) -> Option { Some(Rc::new(|app: &mut App, term: &mut Term| { + let default_start_point = get_current_branch_name(&app.state.repo)?; + let start_point = app.prompt( + term, + &PromptParams { + prompt: "Create and checkout branch starting at:", + create_default_value: Box::new(move |_app| Some(default_start_point.clone())), + ..Default::default() + }, + )?; + let branch_name = app.prompt( term, &PromptParams { - prompt: "Create and checkout branch:", + prompt: "Name for new branch:", ..Default::default() }, )?; - checkout_new_branch_prompt_update(app, term, &branch_name)?; + checkout_new_branch_prompt_update(app, term, &start_point, &branch_name)?; Ok(()) })) } @@ -71,9 +81,14 @@ impl OpTrait for CheckoutNewBranch { } } -fn checkout_new_branch_prompt_update(app: &mut App, term: &mut Term, branch_name: &str) -> Res<()> { +fn checkout_new_branch_prompt_update( + app: &mut App, + term: &mut Term, + start_point: &str, + branch_name: &str, +) -> Res<()> { let mut cmd = Command::new("git"); - cmd.args(["checkout", "-b", branch_name]); + cmd.args(["checkout", "-b", branch_name, start_point]); app.close_menu(); app.run_cmd(term, &[], cmd)?; diff --git a/src/tests/branch.rs b/src/tests/branch.rs index ce189cf4d1..e6f67b2f67 100644 --- a/src/tests/branch.rs +++ b/src/tests/branch.rs @@ -25,7 +25,12 @@ fn switch_branch_input() { #[test] fn checkout_new_branch() { - snapshot!(setup(setup_clone!()), "bcnew"); + snapshot!(setup(setup_clone!()), "bcnew"); +} + +#[test] +fn checkout_new_branch_start_point() { + snapshot!(setup(setup_clone!()), "bcunmergednew"); } #[test] diff --git a/src/tests/snapshots/gitu__tests__branch__checkout_new_branch.snap b/src/tests/snapshots/gitu__tests__branch__checkout_new_branch.snap index 3b0cc6f1ef..1322791533 100644 --- a/src/tests/snapshots/gitu__tests__branch__checkout_new_branch.snap +++ b/src/tests/snapshots/gitu__tests__branch__checkout_new_branch.snap @@ -20,6 +20,6 @@ expression: ctx.redact_buffer() | | ────────────────────────────────────────────────────────────────────────────────| -$ git checkout -b new | +$ git checkout -b new main | Switched to a new branch 'new' | -styles_hash: 2afc72138214b087 +styles_hash: 51d00da50a627344 diff --git a/src/tests/snapshots/gitu__tests__branch__checkout_new_branch_start_point.snap b/src/tests/snapshots/gitu__tests__branch__checkout_new_branch_start_point.snap new file mode 100644 index 0000000000..a5dd1e5697 --- /dev/null +++ b/src/tests/snapshots/gitu__tests__branch__checkout_new_branch_start_point.snap @@ -0,0 +1,25 @@ +--- +source: src/tests/branch.rs +expression: ctx.redact_buffer() +--- +▌On branch new | + | + Recent commits | + c84f226 new unmerged add first commit | + b66a0bf main merged origin/main add initial-file | + | + | + | + | + | + | + | + | + | + | + | + | +────────────────────────────────────────────────────────────────────────────────| +$ git checkout -b new unmerged | +Switched to a new branch 'new' | +styles_hash: 64b6fb8b841715c1