//! Worktree workflow implementations. //! //! - **follow**: Hard-reset a work branch to track a target branch (e.g. main) //! - **take**: Squash-merge changes from a worktree branch into a target branch use crate::error::{ProjectError, Result}; use crate::git::runner::GitRunner; /// Follow workflow: hard-reset work_branch to match target_branch. /// /// This is used when a worktree's work branch needs to catch up with /// the main branch. After this operation, work_branch HEAD will be /// identical to target_branch HEAD. /// /// **Destructive**: Discards any uncommitted changes on work_branch. pub async fn follow(runner: &GitRunner, work_branch: &str, target_branch: &str) -> Result<()> { // Ensure we're on the work branch let current = runner.current_branch().await?; if current != work_branch { runner.checkout(work_branch).await?; } runner.reset_hard(target_branch).await?; Ok(()) } /// Take workflow: squash-merge changes from source_branch into target_branch. /// /// This brings all the work from source_branch into target_branch as a /// single commit. If `auto_commit` is true, the squash is committed /// automatically with a generated message. /// /// Returns the commit hash if auto_commit is true, None otherwise /// (leaving the changes staged for manual commit). pub async fn take( runner: &GitRunner, source_branch: &str, target_branch: &str, auto_commit: bool, ) -> Result> { // Switch to target branch let current = runner.current_branch().await?; if current != target_branch { runner.checkout(target_branch).await?; } // Squash-merge runner.merge_squash(source_branch).await.map_err(|e| { ProjectError::Validation(format!( "squash-merge from '{}' into '{}' failed: {}", source_branch, target_branch, e )) })?; if auto_commit { let message = format!("Squash merge from {}", source_branch); let hash = runner.commit(&message).await?; Ok(Some(hash)) } else { Ok(None) } }