git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC PATCH] add t3420-rebase-topology

From
Martin von Zweigbergk <martinvonz@gmail.com>
Date
Sep 18, 2012, 06:31 UTC
Message-ID
<1347949878-12578-1-git-send-email-martinvonz@gmail.com>

Add more test cases to check that the topology after a rebase is as expected. Conflicts are not considered, but patch-equivalence is. ---

Tests pass and fail as indicated by the suffix (_success/_failure). Your input especially appreciated on whether you agree with the intent of the test cases. For example, do you agree that 'rebase --onto does not re-apply patches in onto' is desirable? And if you do, then do you also agree that 'rebase --root --onto ignores patch in onto' is desirable? How about 'rebase --root is not a no-op'? One might think that --force would be necessary, but on the other hand, if that was the case, the only point (AFAICT) of "git rebase --root <branch>" without --force would be to linearize history, so I instead made the test case confirm that --root without --onto effectively behaves as if --force was also passed.

Feedback on the structure/setup and style is of course also appreciated.

 t/t3420-rebase-topology.sh | 348 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 348 insertions(+)
 create mode 100755 t/t3420-rebase-topology.sh
diff --git a/t/t3420-rebase-topology.sh b/t/t3420-rebase-topology.sh
new file mode 100755
index 0000000..024a2b4
--- /dev/null
+++ b/t/t3420-rebase-topology.sh
@@ -0,0 +1,348 @@
+#!/bin/sh
+
+test_description='effect of rebase on topology'
+. ./test-lib.sh
+
+
+#       q---C---r
+#      /
+# a---b---c---d!--e---p
+#      \
+#       f---g!--h
+#        \
+#         j-------E---k
+#          \       \
+#           n---H---w
+#
+# x---y---B
+#
+#
+# ! = empty
+# uppercase = cherry-picked
+# p = reverted e
+#
+# TODO:
+# prune graph to what's needed
+
+empty () {
+	git commit --allow-empty -m $1 &&
+	git tag $1
+}
+
+cherry_pick () {
+	git cherry-pick -n $1 &&
+	git commit -m $2 &&
+	git tag $2
+}
+
+revert () {
+	git revert -n $1 &&
+	git commit -m $2 &&
+	git tag $2
+}
+
+
+test_expect_success 'setup' '
+	test_commit a &&
+	test_commit b &&
+	test_commit c &&
+	empty d &&
+	test_commit e &&
+	revert e p &&
+	git checkout b &&
+	test_commit f &&
+	empty g &&
+	test_commit h &&
+	git checkout f &&
+	test_commit j &&
+	cherry_pick e E &&
+	test_commit k &&
+	git checkout j &&
+	test_commit n &&
+	cherry_pick h H &&
+	git merge -m w E &&
+	git tag w &&
+	git checkout b &&
+	test_commit q &&
+	cherry_pick c C &&
+	test_commit r &&
+	git checkout --orphan disjoint &&
+	git rm -rf . &&
+	test_commit x &&
+	test_commit y &&
+	cherry_pick b B
+'
+
+reset () {
+	git rebase --abort
+	git reset --hard
+}
+
+test_range () {
+	test "$(git log --reverse --topo-order --format=%s "$1" | xargs)" = "$2"
+}
+
+test_revisions () {
+	expected="$1"
+	shift
+	test "$(git log --format=%s --no-walk=unsorted "$@" | xargs)" = "$expected"
+}
+
+same_revision () {
+	test "$(git rev-parse $1)" = "$(git rev-parse $2)"
+}
+
+# the following 5 (?) tests copy t3400 tests, but check the history rather than status code and/or stdout
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' c j &&
+	same_revision HEAD~2 c &&
+	test_range c.. "f j"
+'
+}
+test_expect_success 'simple rebase' "$(run)"
+test_expect_success 'simple rebase -m' "$(run -m)"
+test_expect_success 'simple rebase -i' "$(run -i)"
+test_expect_success 'simple rebase -p' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' b j &&
+	same_revision HEAD j
+'
+}
+test_expect_success 'rebase is no-op if upstream is an ancestor' "$(run)"
+test_expect_success 'rebase -m is no-op if upstream is an ancestor' "$(run -m)"
+test_expect_success 'rebase -i is no-op if upstream is an ancestor' "$(run -i)"
+test_expect_success 'rebase -p is no-op if upstream is an ancestor' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --force b j &&
+	! same_revision HEAD j &&
+	test_range b.. "f j"
+'
+}
+test_expect_success 'rebase --force' "$(run)"
+test_expect_success 'rebase -m --force' "$(run -m)"
+test_expect_success 'rebase -i --force' "$(run -i)"
+test_expect_failure 'rebase -p --force' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' j b &&
+	same_revision HEAD j
+'
+}
+test_expect_success 'rebase fast-forwards if an ancestor of upstream' "$(run)"
+test_expect_success 'rebase -m fast-forwards if an ancestor of upstream' "$(run -m)"
+test_expect_success 'rebase -i fast-forwards if an ancestor of upstream' "$(run -i)"
+test_expect_success 'rebase -p fast-forwards if an ancestor of upstream' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' p k &&
+	test_range p.. "f j k"
+'
+}
+test_expect_success 'rebase ignores patch in upstream' "$(run)"
+test_expect_failure 'rebase -m ignores patch in upstream' "$(run -m)"
+test_expect_success 'rebase -i ignores patch in upstream' "$(run -i)"
+test_expect_success 'rebase -p ignores patch in upstream' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' c h &&
+	test_range c.. "f h"
+'
+}
+test_expect_success 'rebase ignores empty commit' "$(run)"
+test_expect_success 'rebase -m ignores empty commit' "$(run -m)"
+test_expect_success 'rebase -i ignores empty commit' "$(run -i)"
+test_expect_success 'rebase -p ignores empty commit' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --keep-empty c h &&
+	test_range c.. "f g h"
+'
+}
+test_expect_success 'rebase --keep-empty' "$(run)"
+test_expect_failure 'rebase -m --keep-empty' "$(run -m)"
+test_expect_success 'rebase -i --keep-empty' "$(run -i)"
+test_expect_failure 'rebase -p --keep-empty' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --keep-empty p h &&
+	test_range p.. "f g h"
+'
+}
+test_expect_success 'rebase --keep-empty keeps empty even if already in upstream' "$(run)"
+test_expect_failure 'rebase -m --keep-empty keeps empty even if already in upstream' "$(run -m)"
+test_expect_failure 'rebase -i --keep-empty keeps empty even if already in upstream' "$(run -i)"
+test_expect_failure 'rebase -p --keep-empty keeps empty even if already in upstream' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' E w &&
+	test_range E.. "n H"
+'
+}
+test_expect_success 'rebase after merge' "$(run)"
+test_expect_success 'rebase -m after merge' "$(run -m)"
+test_expect_success 'rebase -i after merge' "$(run -i)"
+
+test_expect_success 'rebase -p is no-op in history with merges' '
+	reset &&
+	git rebase -p j w &&
+	same_revision HEAD w
+'
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' j w &&
+	test_range j.. "E n H" || test_range j.. "n H E"
+'
+}
+test_expect_success 'rebase of history with merges is linearized' "$(run)"
+test_expect_success 'rebase -m of history with merges is linearized' "$(run -m)"
+test_expect_success 'rebase -i of history with merges is linearized' "$(run -i)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --onto p h k &&
+	test_range p.. "j k"
+'
+}
+test_expect_failure 'rebase --onto does not re-apply patches in onto' "$(run)"
+test_expect_failure 'rebase -m --onto does not re-apply patches in onto' "$(run -m)"
+test_expect_failure 'rebase -i --onto does not re-apply patches in onto' "$(run -i)"
+test_expect_failure 'rebase -p --onto does not re-apply patches in onto' "$(run -p)"
+
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --onto f d r &&
+	test_range f.. "q C r"
+'
+}
+test_expect_failure 'rebase --onto does not lose patches in upstream' "$(run)"
+test_expect_success 'rebase -m --onto does not lose patches in upstream' "$(run -m)"
+test_expect_failure 'rebase -i --onto does not lose patches in upstream' "$(run -i)"
+test_expect_failure 'rebase -p --onto does not lose patches in upstream' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --root c &&
+	! same_revision HEAD c &&
+	test_range c "a b c"
+'
+}
+test_expect_success 'rebase --root is not a no-op' "$(run)"
+test_expect_success 'rebase -m --root is not a no-op' "$(run -m)"
+test_expect_success 'rebase -i --root is not a no-op' "$(run -i)"
+test_expect_success 'rebase -p --root is not a no-op' "$(run -p)"
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --root --onto e y &&
+	test_range e.. "x y"
+'
+}
+test_expect_success 'rebase --root --onto' "$(run)"
+test_expect_failure 'rebase -m --root --onto' "$(run -m)"
+test_expect_success 'rebase -i --root --onto' "$(run -i)"
+test_expect_success 'rebase -p --root --onto' "$(run -p)"
+
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --root --onto e B &&
+	test_range e.. "x y"
+'
+}
+test_expect_success 'rebase --root --onto ignores patch in onto' "$(run)"
+test_expect_failure 'rebase -m --root --onto ignores patch in onto' "$(run -m)"
+test_expect_success 'rebase -i --root --onto ignores patch in onto' "$(run -i)"
+test_expect_success 'rebase -p --root --onto ignores patch in onto' "$(run -p)"
+
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' e y &&
+	test_range e.. "x y"
+'
+}
+test_expect_success 'rebase without --root works on disjoint history' "$(run)"
+test_expect_failure 'rebase -m without --root works on disjoint history' "$(run -m)"
+test_expect_success 'rebase -i without --root works on disjoint history' "$(run -i)"
+test_expect_failure 'rebase -p without --root works on disjoint history' "$(run -p)"
+
+
+run () {
+echo '
+	reset &&
+	git rebase '"$@"' --root --onto p k &&
+	test_range p.. "f j k"
+'
+}
+test_expect_success 'rebase --root --onto with merge-base ignores --root' "$(run)"
+test_expect_failure 'rebase -m --root --onto with merge-base ignores --root' "$(run -m)"
+test_expect_success 'rebase -i --root --onto with merge-base ignores --root' "$(run -i)"
+test_expect_success 'rebase -p --root --onto with merge-base ignores --root' "$(run -p)"
+
+test_expect_success 'rebase -p re-creates merge from upstream' '
+	reset &&
+	git rebase -p k w &&
+	same_revision HEAD^ H &&
+	same_revision HEAD^2 k
+'
+
+test_expect_success 'rebase -p re-creates internal merge' '
+	reset &&
+	git rebase -p c w &&
+	test_revisions "f j n E H w" HEAD~4 HEAD~3 HEAD~2 HEAD^2 HEAD^ HEAD
+'
+
+test_expect_success 'rebase -p rebuilds history around dropped commit matching upstream' '
+	reset &&
+	git rebase -p h w &&
+	test_revisions "j E n w" HEAD~2 HEAD^2 HEAD^ HEAD
+'
+
+test_expect_success 'rebase -p drops merge commit when one entire side is dropped' '
+	reset &&
+	git rebase -p p w &&
+	test_range p.. "f j n H"
+'
+
+test_expect_failure 'rebase -p --onto drops commit in <onto>' '
+	reset &&
+	git rebase -p --onto p f w &&
+	test_range p.. "j n H"
+'
+
+test_expect_success 'rebase -p with two paths to $from' '
+	reset &&
+	git rebase -p --onto c j w &&
+	test_revisions "c n E H w" HEAD~3 HEAD~2 HEAD^2 HEAD^ HEAD
+'
+
+test_done
-- 
1.7.11.1.104.ge7b44f1
Next: Junio C Hamano
Message 1 of 75 in “add t3420-rebase-topology”
  1. add t3420-rebase-topologyMartin von Zweigbergk, Sep 18, 2012
  2. Junio C HamanoSep 18, 2012
  3. Martin von ZweigbergkSep 21, 2012
  4. Johannes SixtSep 18, 2012
  5. Martin von ZweigbergkSep 26, 2012
  6. Chris WebbSep 27, 2012
  7. Martin von ZweigbergkSep 28, 2012
  8. Chris WebbSep 29, 2012
  9. 0/7 Rebase topology testMartin von Zweigbergk, May 29, 2013
  10. 1/7 add simple tests of consistency across rebase typesMartin von Zweigbergk, May 29, 2013
  11. Martin von ZweigbergkJun 3, 2013
  12. Junio C HamanoJun 3, 2013
  13. Martin von ZweigbergkJun 3, 2013
  14. 2/7 add tests for rebasing with patch-equivalence presentMartin von Zweigbergk, May 29, 2013
  15. Johannes SixtMay 29, 2013
  16. Martin von ZweigbergkMay 30, 2013
  17. Felipe ContrerasMay 30, 2013
  18. Martin von ZweigbergkMay 30, 2013
  19. Felipe ContrerasMay 30, 2013
  20. Martin von ZweigbergkMay 30, 2013
  21. Johannes SixtMay 30, 2013
  22. Martin von ZweigbergkMay 30, 2013
  23. 3/7 add tests for rebasing of empty commitsMartin von Zweigbergk, May 29, 2013
  24. 4/7 add tests for rebasing rootMartin von Zweigbergk, May 29, 2013
  25. Johannes SixtMay 29, 2013
  26. Martin von ZweigbergkMay 30, 2013
  27. 5/7 add tests for rebasing merged historyMartin von Zweigbergk, May 29, 2013
  28. Johannes SixtMay 29, 2013
  29. Martin von ZweigbergkMay 31, 2013
  30. Johannes SixtMay 29, 2013
  31. 6/7 t3406: modernize styleMartin von Zweigbergk, May 29, 2013
  32. 7/7 tests: move test for rebase messages from t3400 to t3406Martin von Zweigbergk, May 29, 2013
  33. Felipe ContrerasMay 29, 2013
  34. Ramkumar RamachandraMay 29, 2013
  35. Felipe ContrerasMay 29, 2013
  36. 0/7 Rebase topology testMartin von Zweigbergk, May 31, 2013
  37. 1/7 add simple tests of consistency across rebase typesMartin von Zweigbergk, May 31, 2013
  38. 2/7 add tests for rebasing with patch-equivalence presentMartin von Zweigbergk, May 31, 2013
  39. 3/7 add tests for rebasing of empty commitsMartin von Zweigbergk, May 31, 2013
  40. 4/7 add tests for rebasing rootMartin von Zweigbergk, May 31, 2013
  41. 5/7 add tests for rebasing merged historyMartin von Zweigbergk, May 31, 2013
  42. Johannes SixtMay 31, 2013
  43. 5/7 add tests for rebasing merged historyMartin von Zweigbergk, Jun 1, 2013
  44. 6/7 t3406: modernize styleMartin von Zweigbergk, May 31, 2013
  45. 7/7 tests: move test for rebase messages from t3400 to t3406Martin von Zweigbergk, May 31, 2013
  46. 0/7 Rebase topology testMartin von Zweigbergk, Jun 3, 2013
  47. 1/7 add simple tests of consistency across rebase typesMartin von Zweigbergk, Jun 3, 2013
  48. Junio C HamanoJun 3, 2013
  49. Martin von ZweigbergkJun 4, 2013
  50. Junio C HamanoJun 4, 2013
  51. Johannes SixtJun 4, 2013
  52. Martin von ZweigbergkJun 5, 2013
  53. 2/7 add tests for rebasing with patch-equivalence presentMartin von Zweigbergk, Jun 3, 2013
  54. 3/7 add tests for rebasing of empty commitsMartin von Zweigbergk, Jun 3, 2013
  55. 4/7 add tests for rebasing rootMartin von Zweigbergk, Jun 3, 2013
  56. 5/7 add tests for rebasing merged historyMartin von Zweigbergk, Jun 3, 2013
  57. Junio C HamanoJun 4, 2013
  58. Martin von ZweigbergkJun 5, 2013
  59. Johannes SixtJun 5, 2013
  60. 6/7 t3406: modernize styleMartin von Zweigbergk, Jun 3, 2013
  61. 7/7 tests: move test for rebase messages from t3400 to t3406Martin von Zweigbergk, Jun 3, 2013
  62. 0/8 Rebase topology testMartin von Zweigbergk, Jun 7, 2013
  63. 1/7 add simple tests of consistency across rebase typesMartin von Zweigbergk, Jun 7, 2013
  64. 2/7 add tests for rebasing with patch-equivalence presentMartin von Zweigbergk, Jun 7, 2013
  65. 3/7 add tests for rebasing of empty commitsMartin von Zweigbergk, Jun 7, 2013
  66. 4/7 add tests for rebasing rootMartin von Zweigbergk, Jun 7, 2013
  67. 5/7 add tests for rebasing merged historyMartin von Zweigbergk, Jun 7, 2013
  68. 6/7 t3406: modernize styleMartin von Zweigbergk, Jun 7, 2013
  69. 7/7 tests: move test for rebase messages from t3400 to t3406Martin von Zweigbergk, Jun 7, 2013
  70. Junio C HamanoJun 7, 2013
  71. Johannes SixtJun 7, 2013
  72. rebase topology tests: fix commit names on case-insensitive file systemsJohannes Sixt, Jun 18, 2013
  73. Junio C HamanoJun 18, 2013
  74. Martin von ZweigbergkJun 18, 2013
  75. Johannes SixtJun 19, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.