Skip to content

Commit 2d43667

Browse files
committed
Merge branch 'jk/log-cherry-pick-duplicate-patches' into maint
When more than one commit with the same patch ID appears on one side, "git log --cherry-pick A...B" did not exclude them all when a commit with the same patch ID appears on the other side. Now it does. * jk/log-cherry-pick-duplicate-patches: patch-ids: handle duplicate hashmap entries
2 parents 635ff67 + c9e3a4e commit 2d43667

File tree

4 files changed

+48
-4
lines changed

4 files changed

+48
-4
lines changed

patch-ids.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static int init_patch_id_entry(struct patch_id *patch,
8989
return 0;
9090
}
9191

92-
struct patch_id *has_commit_patch_id(struct commit *commit,
92+
struct patch_id *patch_id_iter_first(struct commit *commit,
9393
struct patch_ids *ids)
9494
{
9595
struct patch_id patch;
@@ -104,6 +104,18 @@ struct patch_id *has_commit_patch_id(struct commit *commit,
104104
return hashmap_get_entry(&ids->patches, &patch, ent, NULL);
105105
}
106106

107+
struct patch_id *patch_id_iter_next(struct patch_id *cur,
108+
struct patch_ids *ids)
109+
{
110+
return hashmap_get_next_entry(&ids->patches, cur, ent);
111+
}
112+
113+
int has_commit_patch_id(struct commit *commit,
114+
struct patch_ids *ids)
115+
{
116+
return !!patch_id_iter_first(commit, ids);
117+
}
118+
107119
struct patch_id *add_commit_patch_id(struct commit *commit,
108120
struct patch_ids *ids)
109121
{

patch-ids.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,25 @@ int commit_patch_id(struct commit *commit, struct diff_options *options,
2323
struct object_id *oid, int, int);
2424
int init_patch_ids(struct repository *, struct patch_ids *);
2525
int free_patch_ids(struct patch_ids *);
26+
27+
/* Add a patch_id for a single commit to the set. */
2628
struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *);
27-
struct patch_id *has_commit_patch_id(struct commit *, struct patch_ids *);
29+
30+
/* Returns true if the patch-id of "commit" is present in the set. */
31+
int has_commit_patch_id(struct commit *commit, struct patch_ids *);
32+
33+
/*
34+
* Iterate over all commits in the set whose patch id matches that of
35+
* "commit", like:
36+
*
37+
* struct patch_id *cur;
38+
* for (cur = patch_id_iter_first(commit, ids);
39+
* cur;
40+
* cur = patch_id_iter_next(cur, ids) {
41+
* ... look at cur->commit
42+
* }
43+
*/
44+
struct patch_id *patch_id_iter_first(struct commit *commit, struct patch_ids *);
45+
struct patch_id *patch_id_iter_next(struct patch_id *cur, struct patch_ids *);
2846

2947
#endif /* PATCH_IDS_H */

revision.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,12 +1241,14 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
12411241
/*
12421242
* Have we seen the same patch id?
12431243
*/
1244-
id = has_commit_patch_id(commit, &ids);
1244+
id = patch_id_iter_first(commit, &ids);
12451245
if (!id)
12461246
continue;
12471247

12481248
commit->object.flags |= cherry_flag;
1249-
id->commit->object.flags |= cherry_flag;
1249+
do {
1250+
id->commit->object.flags |= cherry_flag;
1251+
} while ((id = patch_id_iter_next(id, &ids)));
12501252
}
12511253

12521254
free_patch_ids(&ids);

t/t6007-rev-list-cherry-pick-file.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,18 @@ test_expect_success '--count --left-right' '
245245
test_cmp expect actual
246246
'
247247

248+
test_expect_success '--cherry-pick with duplicates on each side' '
249+
git checkout -b dup-orig &&
250+
test_commit dup-base &&
251+
git revert dup-base &&
252+
git cherry-pick dup-base &&
253+
git checkout -b dup-side HEAD~3 &&
254+
test_tick &&
255+
git cherry-pick -3 dup-orig &&
256+
git rev-list --cherry-pick dup-orig...dup-side >actual &&
257+
test_must_be_empty actual
258+
'
259+
248260
# Corrupt the object store deliberately to make sure
249261
# the object is not even checked for its existence.
250262
remove_loose_object () {

0 commit comments

Comments
 (0)