Skip to content

Commit 850e925

Browse files
committed
Merge branch 'pw/rebase-signoff'
"git rebase" has learned to honor "--signoff" option when using backends other than "am" (but not "--preserve-merges"). * pw/rebase-signoff: rebase --keep-empty: always use interactive rebase rebase -p: error out if --signoff is given rebase: extend --signoff support
2 parents d892bee + da27a6f commit 850e925

File tree

8 files changed

+114
-57
lines changed

8 files changed

+114
-57
lines changed

Documentation/git-rebase.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,10 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
364364
Incompatible with the --interactive option.
365365

366366
--signoff::
367-
This flag is passed to 'git am' to sign off all the rebased
368-
commits (see linkgit:git-am[1]). Incompatible with the
369-
--interactive option.
367+
Add a Signed-off-by: trailer to all the rebased commits. Note
368+
that if `--interactive` is given then only commits marked to be
369+
picked, edited or reworded will have the trailer added. Incompatible
370+
with the `--preserve-merges` option.
370371

371372
-i::
372373
--interactive::

git-rebase--am.sh

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -32,60 +32,47 @@ else
3232
fi
3333

3434
ret=0
35-
if test -n "$keep_empty"
36-
then
37-
# we have to do this the hard way. git format-patch completely squashes
38-
# empty commits and even if it didn't the format doesn't really lend
39-
# itself well to recording empty patches. fortunately, cherry-pick
40-
# makes this easy
41-
git cherry-pick ${gpg_sign_opt:+"$gpg_sign_opt"} --allow-empty \
42-
$allow_rerere_autoupdate --right-only "$revisions" \
43-
$allow_empty_message \
44-
${restrict_revision+^$restrict_revision}
45-
ret=$?
46-
else
47-
rm -f "$GIT_DIR/rebased-patches"
35+
rm -f "$GIT_DIR/rebased-patches"
4836

49-
git format-patch -k --stdout --full-index --cherry-pick --right-only \
50-
--src-prefix=a/ --dst-prefix=b/ --no-renames --no-cover-letter \
51-
--pretty=mboxrd \
52-
$git_format_patch_opt \
53-
"$revisions" ${restrict_revision+^$restrict_revision} \
54-
>"$GIT_DIR/rebased-patches"
55-
ret=$?
37+
git format-patch -k --stdout --full-index --cherry-pick --right-only \
38+
--src-prefix=a/ --dst-prefix=b/ --no-renames --no-cover-letter \
39+
--pretty=mboxrd \
40+
$git_format_patch_opt \
41+
"$revisions" ${restrict_revision+^$restrict_revision} \
42+
>"$GIT_DIR/rebased-patches"
43+
ret=$?
5644

57-
if test 0 != $ret
58-
then
59-
rm -f "$GIT_DIR/rebased-patches"
60-
case "$head_name" in
61-
refs/heads/*)
62-
git checkout -q "$head_name"
63-
;;
64-
*)
65-
git checkout -q "$orig_head"
66-
;;
67-
esac
45+
if test 0 != $ret
46+
then
47+
rm -f "$GIT_DIR/rebased-patches"
48+
case "$head_name" in
49+
refs/heads/*)
50+
git checkout -q "$head_name"
51+
;;
52+
*)
53+
git checkout -q "$orig_head"
54+
;;
55+
esac
6856

69-
cat >&2 <<-EOF
57+
cat >&2 <<-EOF
7058
71-
git encountered an error while preparing the patches to replay
72-
these revisions:
59+
git encountered an error while preparing the patches to replay
60+
these revisions:
7361
74-
$revisions
62+
$revisions
7563
76-
As a result, git cannot rebase them.
77-
EOF
78-
return $ret
79-
fi
64+
As a result, git cannot rebase them.
65+
EOF
66+
return $ret
67+
fi
8068

81-
git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
82-
--patch-format=mboxrd \
83-
$allow_rerere_autoupdate \
84-
${gpg_sign_opt:+"$gpg_sign_opt"} <"$GIT_DIR/rebased-patches"
85-
ret=$?
69+
git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
70+
--patch-format=mboxrd \
71+
$allow_rerere_autoupdate \
72+
${gpg_sign_opt:+"$gpg_sign_opt"} <"$GIT_DIR/rebased-patches"
73+
ret=$?
8674

87-
rm -f "$GIT_DIR/rebased-patches"
88-
fi
75+
rm -f "$GIT_DIR/rebased-patches"
8976

9077
if test 0 != $ret
9178
then

git-rebase--interactive.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ pick_one () {
285285
pick_one_preserving_merges "$@" && return
286286
output eval git cherry-pick $allow_rerere_autoupdate $allow_empty_message \
287287
${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
288-
"$strategy_args" $empty_args $ff "$@"
288+
$signoff "$strategy_args" $empty_args $ff "$@"
289289

290290
# If cherry-pick dies it leaves the to-be-picked commit unrecorded. Reschedule
291291
# previous task so this commit is not lost.
@@ -524,10 +524,10 @@ do_pick () {
524524
# resolve before manually running git commit --amend then git
525525
# rebase --continue.
526526
git commit --allow-empty --allow-empty-message --amend \
527-
--no-post-rewrite -n -q -C $sha1 &&
527+
--no-post-rewrite -n -q -C $sha1 $signoff &&
528528
pick_one -n $sha1 &&
529529
git commit --allow-empty --allow-empty-message \
530-
--amend --no-post-rewrite -n -q -C $sha1 \
530+
--amend --no-post-rewrite -n -q -C $sha1 $signoff \
531531
${gpg_sign_opt:+"$gpg_sign_opt"} ||
532532
die_with_patch $sha1 "$(eval_gettext "Could not apply \$sha1... \$rest")"
533533
else

git-rebase--merge.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ continue_merge () {
2727
cmt=$(cat "$state_dir/current")
2828
if ! git diff-index --quiet --ignore-submodules HEAD --
2929
then
30-
if ! git commit ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message \
30+
if ! git commit ${gpg_sign_opt:+"$gpg_sign_opt"} $signoff $allow_empty_message \
3131
--no-verify -C "$cmt"
3232
then
3333
echo "Commit failed, please do not call \"git commit\""

git-rebase.sh

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ preserve_merges=
9393
autosquash=
9494
keep_empty=
9595
allow_empty_message=
96+
signoff=
9697
test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
9798
case "$(git config --bool commit.gpgsign)" in
9899
true) gpg_sign_opt=-S ;;
@@ -122,6 +123,10 @@ read_basic_state () {
122123
allow_rerere_autoupdate="$(cat "$state_dir"/allow_rerere_autoupdate)"
123124
test -f "$state_dir"/gpg_sign_opt &&
124125
gpg_sign_opt="$(cat "$state_dir"/gpg_sign_opt)"
126+
test -f "$state_dir"/signoff && {
127+
signoff="$(cat "$state_dir"/signoff)"
128+
force_rebase=t
129+
}
125130
}
126131

127132
write_basic_state () {
@@ -136,6 +141,7 @@ write_basic_state () {
136141
test -n "$allow_rerere_autoupdate" && echo "$allow_rerere_autoupdate" > \
137142
"$state_dir"/allow_rerere_autoupdate
138143
test -n "$gpg_sign_opt" && echo "$gpg_sign_opt" > "$state_dir"/gpg_sign_opt
144+
test -n "$signoff" && echo "$signoff" >"$state_dir"/signoff
139145
}
140146

141147
output () {
@@ -336,7 +342,13 @@ do
336342
--ignore-whitespace)
337343
git_am_opt="$git_am_opt $1"
338344
;;
339-
--committer-date-is-author-date|--ignore-date|--signoff|--no-signoff)
345+
--signoff)
346+
signoff=--signoff
347+
;;
348+
--no-signoff)
349+
signoff=
350+
;;
351+
--committer-date-is-author-date|--ignore-date)
340352
git_am_opt="$git_am_opt $1"
341353
force_rebase=t
342354
;;
@@ -452,6 +464,11 @@ then
452464
test -z "$interactive_rebase" && interactive_rebase=implied
453465
fi
454466

467+
if test -n "$keep_empty"
468+
then
469+
test -z "$interactive_rebase" && interactive_rebase=implied
470+
fi
471+
455472
if test -n "$interactive_rebase"
456473
then
457474
type=interactive
@@ -470,6 +487,14 @@ then
470487
git_format_patch_opt="$git_format_patch_opt --progress"
471488
fi
472489

490+
if test -n "$signoff"
491+
then
492+
test -n "$preserve_merges" &&
493+
die "$(gettext "error: cannot combine '--signoff' with '--preserve-merges'")"
494+
git_am_opt="$git_am_opt $signoff"
495+
force_rebase=t
496+
fi
497+
473498
if test -z "$rebase_root"
474499
then
475500
case "$#" in

sequencer.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ static GIT_PATH_FUNC(rebase_path_rewritten_pending,
127127
static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
128128
static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
129129
static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
130+
static GIT_PATH_FUNC(rebase_path_signoff, "rebase-merge/signoff")
130131
static GIT_PATH_FUNC(rebase_path_head_name, "rebase-merge/head-name")
131132
static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
132133
static GIT_PATH_FUNC(rebase_path_autostash, "rebase-merge/autostash")
@@ -1604,7 +1605,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
16041605
}
16051606
}
16061607

1607-
if (opts->signoff)
1608+
if (opts->signoff && !is_fixup(command))
16081609
append_signoff(&msgbuf, 0, 0);
16091610

16101611
if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
@@ -2043,6 +2044,11 @@ static int read_populate_opts(struct replay_opts *opts)
20432044
if (file_exists(rebase_path_verbose()))
20442045
opts->verbose = 1;
20452046

2047+
if (file_exists(rebase_path_signoff())) {
2048+
opts->allow_ff = 0;
2049+
opts->signoff = 1;
2050+
}
2051+
20462052
read_strategy_opts(opts, &buf);
20472053
strbuf_release(&buf);
20482054

t/t3421-rebase-topology-linear.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ test_run_rebase () {
199199
"
200200
}
201201
test_run_rebase success ''
202-
test_run_rebase failure -m
202+
test_run_rebase success -m
203203
test_run_rebase success -i
204204
test_run_rebase failure -p
205205

@@ -214,7 +214,7 @@ test_run_rebase () {
214214
"
215215
}
216216
test_run_rebase success ''
217-
test_run_rebase failure -m
217+
test_run_rebase success -m
218218
test_run_rebase success -i
219219
test_run_rebase failure -p
220220

t/t3428-rebase-signoff.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ cat >file <<EOF
1212
a
1313
EOF
1414

15+
# Expected commit message for initial commit after rebase --signoff
16+
cat >expected-initial-signed <<EOF
17+
Initial empty commit
18+
19+
Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/")
20+
EOF
21+
1522
# Expected commit message after rebase --signoff
1623
cat >expected-signed <<EOF
1724
first
@@ -43,4 +50,35 @@ test_expect_success 'rebase --no-signoff does not add a sign-off line' '
4350
test_cmp expected-unsigned actual
4451
'
4552

53+
test_expect_success 'rebase --exec --signoff adds a sign-off line' '
54+
test_when_finished "rm exec" &&
55+
git commit --amend -m "first" &&
56+
git rebase --exec "touch exec" --signoff HEAD^ &&
57+
test_path_is_file exec &&
58+
git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
59+
test_cmp expected-signed actual
60+
'
61+
62+
test_expect_success 'rebase --root --signoff adds a sign-off line' '
63+
git commit --amend -m "first" &&
64+
git rebase --root --keep-empty --signoff &&
65+
git cat-file commit HEAD^ | sed -e "1,/^\$/d" >actual &&
66+
test_cmp expected-initial-signed actual &&
67+
git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
68+
test_cmp expected-signed actual
69+
'
70+
71+
test_expect_success 'rebase -i --signoff fails' '
72+
git commit --amend -m "first" &&
73+
git rebase -i --signoff HEAD^ &&
74+
git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
75+
test_cmp expected-signed actual
76+
'
77+
78+
test_expect_success 'rebase -m --signoff fails' '
79+
git commit --amend -m "first" &&
80+
git rebase -m --signoff HEAD^ &&
81+
git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
82+
test_cmp expected-signed actual
83+
'
4684
test_done

0 commit comments

Comments
 (0)