git log --cherry-pick A..B - 我做错了什么?

git log --cherry-pick A..B - what am I doing wrong?

为了找到分支 working 上的提交,而不是 merged/picked 到 master 但我是 运行

git log --format="%h %aN %ai %f" --cherry-pick --no-merges master..working

据了解here

但是正如所描述的那样here我发现在 master working 上的提交只是由于 cherry 而在提交 ID 上有所不同-采摘。

working 尚未合并到 master,反之亦然。

即使我手动选择从 workingmaster 的提交,它也会显示 运行 上面的命令。

实际上 --cherry-pick 似乎根本没有效果,如 |wc 所示。

我做错了什么?

更新:

实际上,ElpieKay 和 torek 都是正确的,我的初始命令也能奏效。不幸的是,我不知道我们正在使用一些“cherry-pickish”魔法我不知道在 cherry-picking 之后哪些 alters 提交

.

作为,您需要三点符号。但是,仅添加三点符号是不够的:您还需要添加 --left-only--right-only(取决于您将 A 和 [= A...B 的 13=] 部分。

注:

In order to find commits on branch working not merged/picked to master yet [I used] master..working

所以在这里,您需要 --right-only master...working。您也可以保留 --no-merges。如果合并仅出现在 master 上,您实际上并不需要 --no-merges,但这可能是无害的。但是请注意,--no-merges 完全消除了 所有 合并,无论它们的补丁 ID 是什么。

在Git2.30.1(2021年第一季度)之前,当一侧出现多个具有相同补丁ID的提交时,“git log --cherry-pick A...B"(man)没有排除它们所有当具有相同补丁 ID 的提交出现在另一侧时。
现在它确实如此(同样,Git 2.31,2021 年第一季度)。

参见 commit c9e3a4e (12 Jan 2021) by Jeff King (peff)
(由 Junio C Hamano -- gitster -- in commit b69bed2 合并,2021 年 1 月 25 日)

patch-ids: handle duplicate hashmap entries

Reported-by: Arnaud Morin
Signed-off-by: Jeff King

This fixes a bug introduced in dfb7a1b ("patch-ids: stop using a hand-rolled hashmap implementation", 2016-07-29, Git v2.10.0-rc0 -- merge) in which

git rev-list --cherry-pick A...B

will fail to suppress commits reachable from A even if a commit with matching patch-id appears in B.

Around the time of that commit, the algorithm for "--cherry-pick" looked something like this: 0. Traverse all of the commits, marking them as being on the left or right side of the symmetric difference.

  1. Iterate over the left-hand commits, inserting a patch-id struct for each into a hashmap, and pointing commit->util to the patch-id struct.
  2. Iterate over the right-hand commits, checking which are present in the hashmap.
    If so, we exclude the commit from the output and we mark the patch-id as "seen".
  3. Iterate again over the left-hand commits, checking whether commit->util->seen is set; if so, exclude them from the output.

At the end, we'll have eliminated commits from both sides that have a matching patch-id on the other side.
But there's a subtle assumption here: for any given patch-id, we must have exactly one struct representing it.
If two commits from A both have the same patch-id and we allow duplicates in the hashmap, then we run into a problem:

  • a. In step 1, we insert two patch-id structs into the hashmap.

  • b. In step 2, our lookups will find only one of these structs, so only one "seen" flag is marked.

  • c. In step 3, one of the commits in A will have its commit->util->seen set, but the other will not. We'll erroneously output the latter.

Prior to dfb7a1b, our hashmap did not allow duplicates.
Afterwards, it used hashmap_add(), which explicitly does allow duplicates.

At that point, the solution would have been easy: when we are about to add a duplicate, skip doing so and return the existing entry which matches.
But it gets more complicated.

In 683f17e ("patch-ids: replace the seen indicator with a commit pointer", 2016-07-29, Git v2.10.0-rc0 -- merge), our step 3 goes away entirely.
Instead, in step 2, when the right-hand side finds a matching patch_id from the left-hand side, we can directly mark the left-hand patch_id->commit to be omitted.
Solving that would be easy, too; there's a one-to-many relationship of patch-ids to commits, so we just need to keep a list.

But there's more.
Commit b3dfeeb ("rebase: avoid computing unnecessary patch IDs", 2016-07-29, Git v2.10.0-rc0 -- merge) built on that by lazily computing the full patch-ids.
So we don't even know when adding to the hashmap whether two commits truly have the same id.
We'd have to tentatively assign them a list, and then possibly split them apart (possibly into N new structs) at the moment we compute the real patch-ids.
This could work, but it's complicated and error-prone.

Instead, let's accept that we may store duplicates, and teach the lookup side to be more clever.
Rather than asking for a single matching patch-id, it will need to iterate over all matching patch-ids.
This does mean examining every entry in a single hash bucket, but the worst-case for a hash lookup was already doing that.

We'll keep the hashmap details out of the caller by providing a simple iteration interface.
We can retain the simple has_commit_patch_id() interface for the other callers, but we'll simplify its return value into an integer, rather than returning the patch_id struct.
That way they won't be tempted to look at the "commit" field of the return value without iterating.