Skip to content

Commit f15e7cf

Browse files
tylerbraziergitster
authored andcommitted
pull: ff --rebase --autostash works in dirty repo
When `git pull --rebase --autostash` in a dirty repository resulted in a fast-forward, nothing was being autostashed and the pull failed. This was due to a shortcut to avoid running rebase when we can fast-forward, but autostash is ignored on that codepath. Now we will only take the shortcut if autostash is not in effect. Based on a few tests against the git.git repo, the shortcut does not seem to give us significant performance benefits, on Linux at least. Regardless, it is more important to be correct than to be fast. Signed-off-by: Tyler Brazier <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b06d364 commit f15e7cf

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

builtin/pull.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
772772
struct oid_array merge_heads = OID_ARRAY_INIT;
773773
struct object_id orig_head, curr_head;
774774
struct object_id rebase_fork_point;
775+
int autostash;
775776

776777
if (!getenv("GIT_REFLOG_ACTION"))
777778
set_reflog_message(argc, argv);
@@ -800,8 +801,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
800801
if (!opt_rebase && opt_autostash != -1)
801802
die(_("--[no-]autostash option is only valid with --rebase."));
802803

804+
autostash = config_autostash;
803805
if (opt_rebase) {
804-
int autostash = config_autostash;
805806
if (opt_autostash != -1)
806807
autostash = opt_autostash;
807808

@@ -862,16 +863,18 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
862863
die(_("Cannot rebase onto multiple branches."));
863864

864865
if (opt_rebase) {
865-
struct commit_list *list = NULL;
866-
struct commit *merge_head, *head;
867-
868-
head = lookup_commit_reference(orig_head.hash);
869-
commit_list_insert(head, &list);
870-
merge_head = lookup_commit_reference(merge_heads.oid[0].hash);
871-
if (is_descendant_of(merge_head, list)) {
872-
/* we can fast-forward this without invoking rebase */
873-
opt_ff = "--ff-only";
874-
return run_merge();
866+
if (!autostash) {
867+
struct commit_list *list = NULL;
868+
struct commit *merge_head, *head;
869+
870+
head = lookup_commit_reference(orig_head.hash);
871+
commit_list_insert(head, &list);
872+
merge_head = lookup_commit_reference(merge_heads.oid[0].hash);
873+
if (is_descendant_of(merge_head, list)) {
874+
/* we can fast-forward this without invoking rebase */
875+
opt_ff = "--ff-only";
876+
return run_merge();
877+
}
875878
}
876879
return run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point);
877880
} else {

t/t5520-pull.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,24 @@ test_expect_success '--rebase fast forward' '
272272
test_cmp reflog.expected reflog.fuzzy
273273
'
274274

275+
test_expect_success '--rebase --autostash fast forward' '
276+
test_when_finished "
277+
git reset --hard
278+
git checkout to-rebase
279+
git branch -D to-rebase-ff
280+
git branch -D behind" &&
281+
git branch behind &&
282+
git checkout -b to-rebase-ff &&
283+
echo another modification >>file &&
284+
git add file &&
285+
git commit -m mod &&
286+
287+
git checkout behind &&
288+
echo dirty >file &&
289+
git pull --rebase --autostash . to-rebase-ff &&
290+
test "$(git rev-parse HEAD)" = "$(git rev-parse to-rebase-ff)"
291+
'
292+
275293
test_expect_success '--rebase with conflicts shows advice' '
276294
test_when_finished "git rebase --abort; git checkout -f to-rebase" &&
277295
git checkout -b seq &&

0 commit comments

Comments
 (0)