Skip to content

Commit 98c9098

Browse files
committed
Add --force-detach flag to bypass detached HEAD check
1 parent 9a2990f commit 98c9098

File tree

6 files changed

+51
-10
lines changed

6 files changed

+51
-10
lines changed

Documentation/git-absorb.adoc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,17 @@ FLAGS
5353
--force-author::
5454
Generate fixups to commits not made by you
5555

56+
--force-detach::
57+
Generate fixups even when on a non-branch (detached) HEAD
58+
5659
-F::
5760
--one-fixup-per-commit::
5861
Only generate one fixup per commit
5962

6063
-f::
6164
--force::
62-
Skip all safety checks.
63-
Generate fixups to commits not made by you (as if by --force-author) and to non-branch HEADs
65+
Skip all safety checks as if all --force-* flags were givenj
66+
See those flags to understand the full effect of supplying --force.
6467

6568
-w::
6669
--whole-file::

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ or the git-absorb manual page.
102102
## TODO
103103

104104
- implement remote default branch check
105-
- add smaller force flags to disable individual safety checks
106105
- stop using `failure::err_msg` and ensure all error output is actionable by the user
107106
- slightly more log output in the success case
108107
- more tests (esp main module and integration tests)

src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub fn unify<'config>(config: &'config Config, repo: &Repository) -> Config<'con
3636
force_author: config.force_author
3737
|| config.force
3838
|| bool_value(&repo, FORCE_AUTHOR_CONFIG_NAME, FORCE_AUTHOR_DEFAULT),
39+
force_detach: config.force_detach || config.force,
3940
..*config
4041
}
4142
}

src/lib.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ use std::io::Write;
1212
pub struct Config<'a> {
1313
pub dry_run: bool,
1414
pub force_author: bool,
15+
pub force_detach: bool,
16+
// force should only be used to enable oher force_* values when unifiying the config.
17+
// Do not access when disabling individual safety checks.
1518
pub force: bool,
1619
pub base: Option<&'a str>,
1720
pub and_rebase: bool,
@@ -30,7 +33,13 @@ fn run_with_repo(logger: &slog::Logger, config: &Config, repo: &git2::Repository
3033
let config = config::unify(&config, repo);
3134
// have force flag enable all force* flags
3235

33-
let stack = stack::working_stack(repo, config.base, config.force_author, config.force, logger)?;
36+
let stack = stack::working_stack(
37+
repo,
38+
config.base,
39+
config.force_author,
40+
config.force_detach,
41+
logger,
42+
)?;
3443
if stack.is_empty() {
3544
crit!(logger, "No commits available to fix up, exiting");
3645
return Ok(());
@@ -614,7 +623,7 @@ mod tests {
614623
let result = run_with_repo(&logger, &DEFAULT_CONFIG, &ctx.repo);
615624
assert_eq!(
616625
result.err().unwrap().to_string(),
617-
"HEAD is not a branch, use --force to override"
626+
"HEAD is not a branch, use --force-detach to override"
618627
);
619628

620629
let mut revwalk = ctx.repo.revwalk().unwrap();
@@ -645,6 +654,27 @@ mod tests {
645654
assert!(is_something_in_index);
646655
}
647656

657+
#[test]
658+
fn detached_head_with_force_detach_flag() {
659+
let ctx = repo_utils::prepare_and_stage();
660+
repo_utils::detach_head(&ctx);
661+
repo_utils::delete_branch(&ctx.repo, "master");
662+
663+
// run 'git-absorb'
664+
let drain = slog::Discard;
665+
let logger = slog::Logger::root(drain, o!());
666+
let config = Config {
667+
force_detach: true,
668+
..DEFAULT_CONFIG
669+
};
670+
run_with_repo(&logger, &config, &ctx.repo).unwrap();
671+
let mut revwalk = ctx.repo.revwalk().unwrap();
672+
revwalk.push_head().unwrap();
673+
674+
assert_eq!(revwalk.count(), 3);
675+
assert!(nothing_left_in_index(&ctx.repo).unwrap());
676+
}
677+
648678
#[test]
649679
fn detached_head_with_force_flag() {
650680
let ctx = repo_utils::prepare_and_stage();
@@ -805,6 +835,7 @@ mod tests {
805835
const DEFAULT_CONFIG: Config = Config {
806836
dry_run: false,
807837
force_author: false,
838+
force_detach: false,
808839
force: false,
809840
base: None,
810841
and_rebase: false,

src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ struct Cli {
2020
/// Generate fixups to commits not made by you
2121
#[clap(long)]
2222
force_author: bool,
23-
/// Skip all safety checks; generate fixups to commits not made by you (as if by --force-author) and to non-branch HEADs
23+
/// Generate fixups even when on a non-branch (detached) HEAD
24+
#[clap(long)]
25+
force_detach: bool,
26+
/// Skip all safety checks as if all --force-* flags were given
2427
#[clap(long, short)]
2528
force: bool,
2629
/// Display more output
@@ -45,6 +48,7 @@ fn main() {
4548
base,
4649
dry_run,
4750
force_author,
51+
force_detach,
4852
force,
4953
verbose,
5054
and_rebase,
@@ -94,6 +98,7 @@ fn main() {
9498
&git_absorb::Config {
9599
dry_run,
96100
force_author,
101+
force_detach,
97102
force,
98103
base: base.as_deref(),
99104
and_rebase,

src/stack.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,21 @@ pub fn working_stack<'repo>(
88
repo: &'repo git2::Repository,
99
user_provided_base: Option<&str>,
1010
force_author: bool,
11-
force: bool,
11+
force_detach: bool,
1212
logger: &slog::Logger,
1313
) -> Result<Vec<git2::Commit<'repo>>> {
1414
let head = repo.head()?;
1515
debug!(logger, "head found"; "head" => head.name());
1616

1717
if !head.is_branch() {
18-
if !force {
19-
return Err(anyhow!("HEAD is not a branch, use --force to override"));
18+
if !force_detach {
19+
return Err(anyhow!(
20+
"HEAD is not a branch, use --force-detach to override"
21+
));
2022
} else {
2123
warn!(
2224
logger,
23-
"HEAD is not a branch, but --force used to continue."
25+
"HEAD is not a branch, but --force-detach used to continue."
2426
);
2527
}
2628
}

0 commit comments

Comments
 (0)