Skip to content

Commit 9702ab8

Browse files
committed
Skip rebase in traverse for branches behind remote
1 parent 33474d4 commit 9702ab8

6 files changed

Lines changed: 134 additions & 28 deletions

File tree

RELEASE_NOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## New in git-machete 3.39.3
44

5+
- changed: when a branch is behind remote (needs a pull), `git machete traverse` now skips rebase,
6+
just as it did already when branch is diverged from & older than remote (suggested by @lsierant)
57
- fixed: when `git machete traverse` failed on a rebase within a worktree,
68
in certain cases the warning message about changed directory didn't show up (reported by @lsierant)
79

docs/man/git-machete.1

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,9 +2085,11 @@ git machete t[raverse] [\-F|\-\-fetch] [\-l|\-\-list\-commits] [\-M|\-\-merge]
20852085
.sp
20862086
Walk the branches in the order as they occur in branch layout file.
20872087
By default, \fBtraverse\fP starts from the current branch.
2088-
This behavior can, however, be customized using options: \fB\-\-start\-from=\fP, \fB\-\-whole\fP or \fB\-w\fP, \fB\-W\fP\&.
2088+
This behavior can, however, be customized using options: \fB\-\-start\-from=...\fP, \fB\-\-whole\fP (\fB\-w\fP) or \fB\-W\fP\&.
20892089
.sp
2090-
For each branch, the command:
2090+
For each branch, the command performs the following actions:
2091+
.sp
2092+
\fBSync to parent\fP
20912093
.INDENT 0.0
20922094
.IP \(bu 2
20932095
detects if the branch is merged (gray edge) to its parent (aka upstream):
@@ -2102,6 +2104,10 @@ otherwise, if the branch has a red or yellow edge to its parent/upstream (see he
21022104
asks the user whether to \fBrebase\fP (default) or merge (if \fB\-\-merge\fP passed) the branch onto into its upstream branch
21032105
\-\-\- equivalent to \fBgit machete update\fP;
21042106
.UNINDENT
2107+
.UNINDENT
2108+
.sp
2109+
\fBSync to remote\fP
2110+
.INDENT 0.0
21052111
.IP \(bu 2
21062112
if the branch is not tracked on a remote, is ahead of its remote counterpart, or diverged from the counterpart &
21072113
has newer head commit than the counterpart:
@@ -2114,13 +2120,19 @@ otherwise, if the branch diverged from the remote counterpart & has older head c
21142120
.INDENT 2.0
21152121
.IP \(bu 2
21162122
asks the user whether to \fBreset\fP (\fBgit reset \-\-keep\fP) the branch to its remote counterpart
2123+
\-\-\- note that rebase/merge isn\(aqt suggested in that case;
21172124
.UNINDENT
21182125
.IP \(bu 2
21192126
otherwise, if the branch is behind its remote counterpart:
21202127
.INDENT 2.0
21212128
.IP \(bu 2
2122-
asks the user whether to \fBpull\fP the branch;
2129+
asks the user whether to \fBpull\fP the branch
2130+
\-\-\- note that rebase/merge isn\(aqt suggested in that case;
2131+
.UNINDENT
21232132
.UNINDENT
2133+
.sp
2134+
\fBSync to GitHub/GitLab\fP
2135+
.INDENT 0.0
21242136
.IP \(bu 2
21252137
if \fB\-H\fP/\fB\-\-sync\-github\-prs\fP or \fB\-L\fP/\fB\-\-sync\-gitlab\-mrs\fP option is present:
21262138
.INDENT 2.0
@@ -2131,18 +2143,18 @@ asks the user whether to \fBretarget\fP the PR/MR if it exists for the given bra
21312143
and its base/target branch in GitHub/GitLab is different than the upstream in machete file
21322144
(just as \fBgit machete github retarget\-pr\fP and \fBgit machete gitlab retarget\-mr\fP would do);
21332145
.UNINDENT
2146+
.UNINDENT
2147+
.sp
2148+
\fBStatus\fP
2149+
.INDENT 0.0
21342150
.IP \(bu 2
2135-
and finally, if any of the above operations has been successfully completed:
2151+
finally, if any of the above operations has been successfully completed:
21362152
.INDENT 2.0
21372153
.IP \(bu 2
21382154
prints the updated \fBstatus\fP\&.
21392155
.UNINDENT
21402156
.UNINDENT
21412157
.sp
2142-
By default \fBtraverse\fP asks if the branch should be pushed. This behavior can, however, be changed with the \fBmachete.traverse.push\fP configuration key.
2143-
It can also be customized using options: \fB\-\-[no\-]push\fP or \fB\-\-[no\-]push\-untracked\fP \-\-\- the order of the flags defines their precedence over each other
2144-
(the one on the right overriding the ones on the left). More on them in the \fBOptions\fP section below.
2145-
.sp
21462158
If the traverse flow is stopped (typically due to merge/rebase conflicts), just run \fBgit machete traverse\fP after the merge/rebase is finished.
21472159
It will pick up the walk from the current branch.
21482160
Unlike with \fBgit rebase\fP or \fBgit cherry\-pick\fP, there is no special \fB\-\-continue\fP flag, as \fBtraverse\fP is stateless.

docs/source/cli/traverse.rst

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ traverse
2626
2727
Walk the branches in the order as they occur in branch layout file.
2828
By default, ``traverse`` starts from the current branch.
29-
This behavior can, however, be customized using options: ``--start-from=``, ``--whole`` or ``-w``, ``-W``.
29+
This behavior can, however, be customized using options: ``--start-from=...``, ``--whole`` (``-w``) or ``-W``.
3030

31-
For each branch, the command:
31+
For each branch, the command performs the following actions:
32+
33+
**Sync to parent**
3234

3335
* detects if the branch is merged (:gray:`gray` edge) to its parent (aka upstream):
3436

@@ -39,6 +41,8 @@ For each branch, the command:
3941
- asks the user whether to **rebase** (default) or merge (if ``--merge`` passed) the branch onto into its upstream branch
4042
--- equivalent to ``git machete update``;
4143

44+
**Sync to remote**
45+
4246
* if the branch is not tracked on a remote, is ahead of its remote counterpart, or diverged from the counterpart &
4347
has newer head commit than the counterpart:
4448

@@ -47,10 +51,14 @@ For each branch, the command:
4751
* otherwise, if the branch diverged from the remote counterpart & has older head commit than the counterpart:
4852

4953
- asks the user whether to **reset** (``git reset --keep``) the branch to its remote counterpart
54+
--- note that rebase/merge isn't suggested in that case;
5055

5156
* otherwise, if the branch is behind its remote counterpart:
5257

53-
- asks the user whether to **pull** the branch;
58+
- asks the user whether to **pull** the branch
59+
--- note that rebase/merge isn't suggested in that case;
60+
61+
**Sync to GitHub/GitLab**
5462

5563
* if ``-H``/``--sync-github-prs`` or ``-L``/``--sync-gitlab-mrs`` option is present:
5664

@@ -60,13 +68,11 @@ For each branch, the command:
6068
and its base/target branch in GitHub/GitLab is different than the upstream in machete file
6169
(just as ``git machete github retarget-pr`` and ``git machete gitlab retarget-mr`` would do);
6270

63-
* and finally, if any of the above operations has been successfully completed:
71+
**Status**
6472

65-
- prints the updated ``status``.
73+
* finally, if any of the above operations has been successfully completed:
6674

67-
By default ``traverse`` asks if the branch should be pushed. This behavior can, however, be changed with the ``machete.traverse.push`` configuration key.
68-
It can also be customized using options: ``--[no-]push`` or ``--[no-]push-untracked`` --- the order of the flags defines their precedence over each other
69-
(the one on the right overriding the ones on the left). More on them in the **Options** section below.
75+
- prints the updated ``status``.
7076

7177
If the traverse flow is stopped (typically due to merge/rebase conflicts), just run ``git machete traverse`` after the merge/rebase is finished.
7278
It will pick up the walk from the current branch.

git_machete/client/traverse.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,16 @@ def traverse(
223223

224224
use_merge = opt_merge or (branch in self.annotations and self.annotations[branch].qualifiers.update_with_merge)
225225

226+
skipping_parent_sync = False
227+
226228
if needs_slide_out:
227229
# Avoid unnecessary fork point check if we already know that the
228230
# branch qualifies for slide out;
229231
# neither rebase nor merge will be suggested in such case anyway.
230232
needs_parent_sync: bool = False
231-
elif s == SyncToRemoteStatus.DIVERGED_FROM_AND_OLDER_THAN_REMOTE:
232-
# Avoid unnecessary fork point check if we already know that the
233-
# branch qualifies for resetting to remote counterpart;
234-
# neither rebase nor merge will be suggested in such case anyway.
233+
elif s in (SyncToRemoteStatus.BEHIND_REMOTE, SyncToRemoteStatus.DIVERGED_FROM_AND_OLDER_THAN_REMOTE):
235234
needs_parent_sync = False
235+
skipping_parent_sync = bool(upstream)
236236
elif use_merge:
237237
needs_parent_sync = bool(
238238
upstream and not self._git.is_ancestor_or_equal(upstream.full_name(), branch.full_name()))
@@ -369,6 +369,15 @@ def traverse(
369369
elif ans in ('q', 'quit'):
370370
return
371371

372+
if skipping_parent_sync:
373+
assert upstream is not None
374+
self._print_new_line(False)
375+
if s == SyncToRemoteStatus.BEHIND_REMOTE:
376+
reason = "behind its remote counterpart"
377+
else:
378+
reason = "diverged from (and has older commits than) its remote counterpart"
379+
print(f"Skipping sync of {bold(branch)} with {bold(upstream)}; {bold(branch)} is {reason}")
380+
372381
if needs_retarget_pr:
373382
any_action_suggested = True
374383
assert pr is not None

git_machete/generated_docs.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,9 +1447,11 @@
14471447
14481448
Walk the branches in the order as they occur in branch layout file.
14491449
By default, `traverse` starts from the current branch.
1450-
This behavior can, however, be customized using options: `--start-from=`, `--whole` or `-w`, `-W`.
1450+
This behavior can, however, be customized using options: `--start-from=...`, `--whole` (`-w`) or `-W`.
14511451
1452-
For each branch, the command:
1452+
For each branch, the command performs the following actions:
1453+
1454+
<b>Sync to parent</b>
14531455
14541456
* detects if the branch is merged (<gray>gray</gray> edge) to its parent (aka upstream):
14551457
@@ -1460,6 +1462,8 @@
14601462
- asks the user whether to <b>rebase</b> (default) or merge (if `--merge` passed) the branch onto into its upstream branch
14611463
— equivalent to `git machete update`;
14621464
1465+
<b>Sync to remote</b>
1466+
14631467
* if the branch is not tracked on a remote, is ahead of its remote counterpart, or diverged from the counterpart &
14641468
has newer head commit than the counterpart:
14651469
@@ -1468,10 +1472,14 @@
14681472
* otherwise, if the branch diverged from the remote counterpart & has older head commit than the counterpart:
14691473
14701474
- asks the user whether to <b>reset</b> (`git reset --keep`) the branch to its remote counterpart
1475+
— note that rebase/merge isn't suggested in that case;
14711476
14721477
* otherwise, if the branch is behind its remote counterpart:
14731478
1474-
- asks the user whether to <b>pull</b> the branch;
1479+
- asks the user whether to <b>pull</b> the branch
1480+
— note that rebase/merge isn't suggested in that case;
1481+
1482+
<b>Sync to GitHub/GitLab</b>
14751483
14761484
* if `-H`/`--sync-github-prs` or `-L`/`--sync-gitlab-mrs` option is present:
14771485
@@ -1481,13 +1489,11 @@
14811489
and its base/target branch in GitHub/GitLab is different than the upstream in machete file
14821490
(just as `git machete github retarget-pr` and `git machete gitlab retarget-mr` would do);
14831491
1484-
* and finally, if any of the above operations has been successfully completed:
1492+
<b>Status</b>
14851493
1486-
- prints the updated `status`.
1494+
* finally, if any of the above operations has been successfully completed:
14871495
1488-
By default `traverse` asks if the branch should be pushed. This behavior can, however, be changed with the `machete.traverse.push` configuration key.
1489-
It can also be customized using options: `--[no-]push` or `--[no-]push-untracked` — the order of the flags defines their precedence over each other
1490-
(the one on the right overriding the ones on the left). More on them in the <b>Options</b> section below.
1496+
- prints the updated `status`.
14911497
14921498
If the traverse flow is stopped (typically due to merge/rebase conflicts), just run `git machete traverse` after the merge/rebase is finished.
14931499
It will pick up the walk from the current branch.

tests/test_traverse.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# flake8: noqa: E501
12
import os
23

34
import pytest
@@ -1070,6 +1071,8 @@ def test_traverse_start_from_branch_names(self) -> None:
10701071
|
10711072
o-ignore-trailing * (diverged from & older than origin)
10721073
1074+
Skipping sync of ignore-trailing with hotfix/add-trigger; ignore-trailing is diverged from (and has older commits than) its remote counterpart
1075+
10731076
Branch ignore-trailing diverged from (and has older commits than) its remote counterpart origin/ignore-trailing.
10741077
Resetting branch ignore-trailing to the commit pointed by origin/ignore-trailing...
10751078
@@ -1230,6 +1233,8 @@ def test_traverse_start_from_case_insensitive_special_values(self) -> None:
12301233
|
12311234
o-ignore-trailing * (diverged from & older than origin)
12321235
1236+
Skipping sync of ignore-trailing with hotfix/add-trigger; ignore-trailing is diverged from (and has older commits than) its remote counterpart
1237+
12331238
Branch ignore-trailing diverged from (and has older commits than) its remote counterpart origin/ignore-trailing.
12341239
Resetting branch ignore-trailing to the commit pointed by origin/ignore-trailing...
12351240
Checking out call-ws... OK
@@ -1332,6 +1337,8 @@ def test_traverse_branch_priority_over_special_values(self) -> None:
13321337
|
13331338
o-ignore-trailing * (diverged from & older than origin)
13341339
1340+
Skipping sync of ignore-trailing with hotfix/add-trigger; ignore-trailing is diverged from (and has older commits than) its remote counterpart
1341+
13351342
Branch ignore-trailing diverged from (and has older commits than) its remote counterpart origin/ignore-trailing.
13361343
Resetting branch ignore-trailing to the commit pointed by origin/ignore-trailing...
13371344
@@ -1948,3 +1955,67 @@ def test_traverse_rebase_conflict(self) -> None:
19481955
Rebasing feature onto master...
19491956
"""
19501957
)
1958+
1959+
def test_traverse_behind_remote_with_red_edge(self) -> None:
1960+
create_repo_with_remote()
1961+
new_branch("master")
1962+
commit()
1963+
new_branch("feature")
1964+
commit()
1965+
commit()
1966+
push()
1967+
reset_to("HEAD~")
1968+
check_out("master")
1969+
commit()
1970+
push()
1971+
check_out("feature")
1972+
1973+
rewrite_branch_layout_file("master\n\tfeature")
1974+
1975+
assert_success(
1976+
["traverse", "-y"],
1977+
"""
1978+
Skipping sync of feature with master; feature is behind its remote counterpart
1979+
1980+
Branch feature is behind its remote counterpart origin/feature.
1981+
Pulling feature (fast-forward only) from origin...
1982+
1983+
master
1984+
|
1985+
x-feature *
1986+
1987+
Reached branch feature which has no successor; nothing left to update
1988+
"""
1989+
)
1990+
1991+
def test_traverse_diverged_from_and_older_with_red_edge(self) -> None:
1992+
create_repo_with_remote()
1993+
new_branch("master")
1994+
commit()
1995+
new_branch("feature")
1996+
commit()
1997+
push()
1998+
with fixed_author_and_committer_date_in_past():
1999+
amend_commit()
2000+
check_out("master")
2001+
commit()
2002+
push()
2003+
check_out("feature")
2004+
2005+
rewrite_branch_layout_file("master\n\tfeature")
2006+
2007+
assert_success(
2008+
["traverse", "-y"],
2009+
"""
2010+
Skipping sync of feature with master; feature is diverged from (and has older commits than) its remote counterpart
2011+
2012+
Branch feature diverged from (and has older commits than) its remote counterpart origin/feature.
2013+
Resetting branch feature to the commit pointed by origin/feature...
2014+
2015+
master
2016+
|
2017+
x-feature *
2018+
2019+
Reached branch feature which has no successor; nothing left to update
2020+
"""
2021+
)

0 commit comments

Comments
 (0)