"git rebase -i" can be very dangerous if used on an already published history. This code detects that one is rewriting a commit that is an ancestor of a remote-tracking branch, and warns the user through the editor. Signed-off-by: Lucien Kong <Lucien.Kong@xxxxxxxxxxxxxxx> Signed-off-by: Valentin Duperray <Valentin.Duperray@xxxxxxxxxxxxxxx> Signed-off-by: Franck Jonas <Franck.Jonas@xxxxxxxxxxxxxxx> Signed-off-by: Thomas Nguy <Thomas.Nguy@xxxxxxxxxxxxxxx> Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@xxxxxxxxxxxxxxx> Signed-off-by: Matthieu Moy <Matthieu.Moy@xxxxxxxxxxxxxxx> --- For now, the code only warns the user; he can't revert back to his original state. We agree with everyone that he should be given a way to abort the rebase. git-rebase--interactive.sh | 17 +++++++++++++++++ t/t3404-rebase-interactive.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 0 deletions(-) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 0c19b7c..67b5faf 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -684,6 +684,20 @@ rearrange_squash () { rm -f "$1.sq" "$1.rearranged" } +# Add a warning notification at the end of each pick or fixup/squash +# line of the todo list, providing the picking commit is already +# published. +warn_published () { + cat "$1" | while read -r command sha1 message + do + test -n "$sha1" || break + if test -n "$(git branch -r --contains "$sha1")" + then + printf "%s\n" "$(sed -e "/"$sha1"/ s|$| [Published]|" "$1")" >"$1" + fi + done +} + case "$action" in continue) # do we have anything to commit? @@ -857,6 +871,7 @@ fi test -s "$todo" || echo noop >> "$todo" test -n "$autosquash" && rearrange_squash "$todo" +warn_published "$todo" cat >> "$todo" << EOF # Rebase $shortrevisions onto $shortonto @@ -869,6 +884,8 @@ cat >> "$todo" << EOF # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # +# Warning: [Published] means that the commit has already been published +# # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 025c1c6..f7c31c1 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -755,4 +755,30 @@ test_expect_success 'rebase-i history with funny messages' ' test_cmp expect actual ' +test_expect_success 'warn before rewriting published history' ' + test_when_finished "rm -rf git.git git" && + git init git.git && + git clone git && + ( + cd git && + test_commit one_commit main.txt one_commit && + test_commit two_commit main.txt two_commit && + test_commit three_commit main.txt three_commit && + git push --all && + test_commit four_commit main.txt four_commit && + FAKE_LINES="1 2 3" && + export FAKE_LINES && + tmp=$(git rebase -i HEAD~3 | sed -n 2,4p) && + echo "$tmp" >actual && + tmp=$(git cherry --abbrev=7 HEAD~3 | sed -e 's/+[[:space:]]//g') && + two_sha1=$(echo "$tmp" | sed -n 1p) && + three_sha1=$(echo "$tmp" | sed -n 2p) && + four_sha1=$(echo "$tmp" | sed -n 3p) && + echo "pick $two_sha1 two_commit [Published]" >expected && + echo "pick $three_sha1 three_commit [Published]" >>expected && + echo "pick $four_sha1 four_commit" >>expected && + test_cmp expected actual + ) +' + test_done -- 1.7.8 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html