Skip to content

Commit 93105ab

Browse files
jerry-skydiogitster
authored andcommitted
patch-id: fix patch-id for mode changes
Currently patch-id as used in rebase and cherry-pick does not account for file modes if the file is modified. One consequence of this is that if you have a local patch that changes modes, but upstream has applied an outdated version of the patch that doesn't include that mode change, "git rebase" will drop your local version of the patch along with your mode changes. It also means that internal patch-id doesn't produce the same output as the builtin, which does account for mode changes due to them being part of diff output. Fix by adding mode to the patch-id if it has changed, in the same format that would be produced by diff, so that it is compatible with builtin patch-id. Signed-off-by: Jerry Zhang <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0df19eb commit 93105ab

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

diff.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6224,6 +6224,11 @@ static int diff_get_patch_id(struct diff_options *options, struct object_id *oid
62246224
} else if (p->two->mode == 0) {
62256225
patch_id_add_string(&ctx, "deletedfilemode");
62266226
patch_id_add_mode(&ctx, p->one->mode);
6227+
} else if (p->one->mode != p->two->mode) {
6228+
patch_id_add_string(&ctx, "oldmode");
6229+
patch_id_add_mode(&ctx, p->one->mode);
6230+
patch_id_add_string(&ctx, "newmode");
6231+
patch_id_add_mode(&ctx, p->two->mode);
62276232
}
62286233

62296234
if (diff_header_only) {

t/t3419-rebase-patch-id.sh

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,17 @@ test_expect_success 'setup: 500 lines' '
4848
git branch -f squashed main &&
4949
git checkout -q -f squashed &&
5050
git reset -q --soft HEAD~2 &&
51-
git commit -q -m squashed
51+
git commit -q -m squashed &&
52+
53+
git branch -f mode main &&
54+
git checkout -q -f mode &&
55+
test_chmod +x file &&
56+
git commit -q -a --amend &&
57+
58+
git branch -f modeother other &&
59+
git checkout -q -f modeother &&
60+
test_chmod +x file &&
61+
git commit -q -a --amend
5262
'
5363

5464
test_expect_success 'detect upstream patch' '
@@ -71,6 +81,13 @@ test_expect_success 'detect upstream patch binary' '
7181
test_when_finished "rm .gitattributes"
7282
'
7383

84+
test_expect_success 'detect upstream patch modechange' '
85+
git checkout -q modeother^{} &&
86+
git rebase mode &&
87+
git rev-list mode...HEAD~ >revs &&
88+
test_must_be_empty revs
89+
'
90+
7491
test_expect_success 'do not drop patch' '
7592
git checkout -q other^{} &&
7693
test_must_fail git rebase squashed &&
@@ -85,4 +102,16 @@ test_expect_success 'do not drop patch binary' '
85102
test_when_finished "rm .gitattributes"
86103
'
87104

105+
test_expect_success 'do not drop patch modechange' '
106+
git checkout -q modeother^{} &&
107+
git rebase other &&
108+
cat >expected <<-\EOF &&
109+
diff --git a/file b/file
110+
old mode 100644
111+
new mode 100755
112+
EOF
113+
git diff HEAD~ >modediff &&
114+
test_cmp expected modediff
115+
'
116+
88117
test_done

0 commit comments

Comments
 (0)