diff --git a/git-filter-repo b/git-filter-repo index c1ff923..4532a16 100755 --- a/git-filter-repo +++ b/git-filter-repo @@ -1870,6 +1870,11 @@ EXAMPLES "merge commits have no file changes, they can be pruned. The " "default ('auto') is to only prune empty merge commits which " "become degenerate (not which started as such).")) + parents.add_argument('--no-ff', action='store_true', + help=_("Even if the first parent is or becomes an ancestor of another " + "parent, do not prune it. This modifies how " + "--prune-degenerate behaves, and may be useful in projects who " + "always use merge --no-ff.")) callback = parser.add_argument_group(title=_("Generic callback code snippets")) callback.add_argument('--filename-callback', metavar="FUNCTION_BODY", @@ -3034,6 +3039,12 @@ class RepoFilter(object): self._orig_graph.is_ancestor(orig_parents[cur], orig_parents[other]): continue + # Some folks want their history to have all first parents be merge + # commits (except for any root commits), and always do a merge --no-ff. + # For such folks, don't remove the first parent even if it's an + # ancestor of other commits. + if self._args.no_ff and cur == 0: + continue # Okay so the cur-th parent is an ancestor of the other-th parent, # and it wasn't that way in the original repository; mark the # cur-th parent as removable. diff --git a/t/t9390-filter-repo.sh b/t/t9390-filter-repo.sh index ea7508f..4003759 100755 --- a/t/t9390-filter-repo.sh +++ b/t/t9390-filter-repo.sh @@ -47,6 +47,7 @@ filter_testcase empty less-empty-keepme --path keepme --prune-empty=never \ filter_testcase degenerate degenerate-keepme --path moduleA/keepme filter_testcase degenerate degenerate-moduleA --path moduleA filter_testcase degenerate degenerate-globme --path-glob *me +filter_testcase degenerate degenerate-keepme-noff --path moduleA/keepme --no-ff filter_testcase unusual unusual-filtered --path '' filter_testcase unusual unusual-mailmap --mailmap ../t9390/sample-mailmap diff --git a/t/t9390/degenerate-keepme-noff b/t/t9390/degenerate-keepme-noff new file mode 100644 index 0000000..d28c7a4 --- /dev/null +++ b/t/t9390/degenerate-keepme-noff @@ -0,0 +1,113 @@ +feature done +blob +mark :1 +data 10 +keepme v1 + +reset refs/heads/master +commit refs/heads/master +mark :2 +author Full Name 2000000000 +0100 +committer Full Name 2000000000 +0100 +data 2 +A +M 100644 :1 moduleA/keepme + +blob +mark :3 +data 10 +keepme v2 + +commit refs/heads/branchO +mark :4 +author Full Name 2000050000 +0100 +committer Full Name 2000050000 +0100 +data 2 +G +from :2 +M 100644 :3 moduleA/keepme + +commit refs/heads/branchI +mark :5 +author Full Name 2000070000 +0100 +committer Full Name 2000070000 +0100 +data 29 +I: Merge commit 'D' into 'H' +from :4 +merge :2 + +commit refs/heads/branchO +mark :6 +author Full Name 2000080000 +0100 +committer Full Name 2000080000 +0100 +data 29 +J: Merge commit 'H' into 'D' +from :2 +merge :4 + +blob +mark :7 +data 10 +keepme v3 + +commit refs/heads/branchO +mark :8 +author Full Name 2000092000 +0100 +committer Full Name 2000092000 +0100 +data 2 +L +from :6 +M 100644 :7 moduleA/keepme + +commit refs/heads/master +mark :9 +author Full Name 2000099000 +0100 +committer Full Name 2000099000 +0100 +data 29 +P: Merge commit 'M' into 'N' +from :2 +merge :8 + +blob +mark :10 +data 10 +keepme v4 + +commit refs/heads/master +mark :11 +author Full Name 3000000000 +0100 +committer Full Name 3000000000 +0100 +data 2 +Q +from :9 +M 100644 :10 moduleA/keepme + +blob +mark :12 +data 10 +keepme v5 + +commit refs/heads/master +mark :13 +author Full Name 3000030000 +0100 +committer Full Name 3000030000 +0100 +data 2 +T +from :11 +M 100644 :12 moduleA/keepme + +blob +mark :14 +data 10 +keepme v6 + +commit refs/heads/master +mark :15 +author Full Name 3000060000 +0100 +committer Full Name 3000060000 +0100 +data 2 +W +from :13 +M 100644 :14 moduleA/keepme + +done