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
,反之亦然。
即使我手动选择从 working
到 master
的提交,它也会显示 运行 上面的命令。
实际上 --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.
- 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.
- 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".
- 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.
为了找到分支 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
,反之亦然。
即使我手动选择从 working
到 master
的提交,它也会显示 运行 上面的命令。
实际上 --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 tomaster
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 entriesReported-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 whichgit rev-list --cherry-pick A...B
will fail to suppress commits reachable from
A
even if a commit with matching patch-id appears inB
.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.
- 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.- 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".- 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 fromA
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 usedhashmap_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 matchingpatch_id
from the left-hand side, we can directly mark the left-handpatch_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 simplehas_commit_patch_id()
interface for the other callers, but we'll simplify its return value into an integer, rather than returning thepatch_id
struct.
That way they won't be tempted to look at the "commit" field of the return value without iterating.