在版本控制系统中找到方向可能很棘手。对于新手来说,这可能会让人感到不知所措,但精通术语和像 Git 这样的版本控制系统的基础知识是开始为开源做贡献的初步步骤之一。
熟悉 Git 还可以帮助您摆脱开源旅程中的棘手情况。Git 功能强大,让您感到掌控一切——没有一种方法您无法恢复到工作版本。
这是一个例子,帮助您理解 cherry-picking 的重要性。假设您在一个分支中进行了多次提交,但您意识到这是错误的分支!您现在该怎么办?您可以选择在正确的分支中重复所有更改并进行新的提交,或者将该分支合并到正确的分支中。等等,前者太繁琐了,您可能不想做后者。那么,有办法吗?是的,Git 为您考虑到了。这就是 cherry-picking 发挥作用的地方。顾名思义,您可以使用它从一个分支中手动挑选一个提交并将其转移到另一个分支中。
使用 cherry-picking 有多种原因。以下是其中三个。
避免重复劳动
当您可以将相同的提交复制到另一个分支时,无需在不同的分支中重做相同的更改。请注意,cherry-picking 提交将在另一个分支中创建一个具有新哈希值的新提交,因此如果您看到不同的提交哈希值,请不要感到困惑。
如果您想知道什么是提交哈希值以及它是如何生成的,这里有一个注释可以帮助您:提交哈希值是使用 SHA-1 算法生成的字符串。SHA-1 算法接受一个输入并输出一个唯一的 40 个字符的哈希值。如果您使用的是 POSIX 系统,请尝试在您的终端中运行此命令
$ echo -n "commit" | openssl sha1
这将输出一个唯一的 40 个字符的哈希值,4015b57a143aec5156fd1444a017a32137a3fd0f
。此哈希值表示字符串 commit
。
当您进行提交时,Git 生成的 SHA-1 哈希值代表的不仅仅是一个字符串。它代表
sha1(
meta data
commit message
committer
commit date
author
authoring date
Hash of the entire tree object
)
这解释了为什么即使您对代码进行最细微的更改,也会得到唯一的提交哈希值。即使是单个更改也不会被忽视。这是因为 Git 具有完整性。
撤消/恢复丢失的更改
当您想要恢复到工作版本时,Cherry-picking 会非常方便。当多个开发人员在同一个代码库上工作时,更改很可能丢失,并且最新版本会移动到过时或无法工作的版本。这就是将提交 cherry-picking 到工作版本可以成为救星的地方。
它是如何工作的?
假设有两个分支,feature1
和 feature2
,您想将提交从 feature1
应用到 feature2
。
在 feature1
分支上,运行 git log
命令,并复制您要 cherry-pick 的提交哈希值。您可以看到一系列类似于以下代码示例的提交。 “commit” 之后的字母数字代码是您需要复制的提交哈希值。 为了方便起见,您可以选择复制前六个字符(本例中为 966cf3
)
commit 966cf3d08b09a2da3f2f58c0818baa37184c9778 (HEAD -> master)
Author: manaswinidas <me@example.com>
Date: Mon Mar 8 09:20:21 2021 +1300
add instructions
然后切换到 feature2
并在您刚从日志中获得的哈希值上运行 git cherry-pick
$ git checkout feature2
$ git cherry-pick 966cf3.
如果该分支不存在,请使用 git checkout -b feature2
创建它。
这里有一个陷阱:您可能会遇到以下情况
$ git cherry-pick 966cf3
On branch feature2
You are currently cherry-picking commit 966cf3d.
nothing to commit, working tree clean
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:
git commit --allow-empty
Otherwise, please use 'git reset'
不要惊慌。只需按照建议运行 git commit --allow-empty
$ git commit --allow-empty
[feature2 afb6fcb] add instructions
Date: Mon Mar 8 09:20:21 2021 +1300
这将打开您的默认编辑器,并允许您编辑提交消息。如果您没有要添加的内容,则可以保存现有消息。
您成功进行了第一次 cherry-pick。如上所述,如果您在分支 feature2
上运行 git log
,您将看到不同的提交哈希值。这是一个例子
commit afb6fcb87083c8f41089cad58deb97a5380cb2c2 (HEAD -> feature2)
Author: manaswinidas <me@example.com>
Date: Mon Mar 8 09:20:21 2021 +1300
add instructions
不要对不同的提交哈希值感到困惑。这只是区分 feature1
和 feature2
中的提交。
Cherry-pick 多个提交
但是,如果您要 cherry-pick 多个提交怎么办?您可以使用
git cherry-pick <commit-hash1> <commit-hash2>... <commit-hashn>
请注意,您不必使用整个提交哈希值;您可以使用前五个或六个字符。
同样,这也很繁琐。如果您要 cherry-pick 的提交是一系列连续的提交怎么办?这种方法太麻烦了。别担心;有一种更简单的方法。
假设您有两个分支
feature1
包括您要复制的提交(从commitA
(较旧的)到commitB
)。feature2
是您要将提交从feature1
转移到的分支。
然后
- 输入
git checkout <feature1>
。 - 获取
commitA
和commitB
的哈希值。 - 输入
git checkout <branchB>
。 - 输入
git cherry-pick <commitA>^..<commitB>
(请注意,这包括commitA
和commitB
)。 - 如果您遇到合并冲突,像往常一样解决它,然后键入
git cherry-pick --continue
以恢复 cherry-pick 过程。
重要的 cherry-pick 选项
以下是 Git 文档 中您可以与 cherry-pick
命令一起使用的一些有用选项
-e
,--edit
:使用此选项,git cherry-pick
允许您在提交之前编辑提交消息。-s
,--signoff
:在提交消息末尾添加“Signed-off-by”行。有关更多信息,请参阅 git-commit(1) 中的 signoff 选项。-S[<keyid>]
,--gpg-sign[=<keyid>]
:这些是 GPG 签名提交。keyid
参数是可选的,默认为提交者身份;如果指定,则必须紧跟选项,中间没有空格。--ff
:如果当前 HEAD 与 cherry-pick 的提交的父级相同,则将执行到此提交的快进。
以下是一些其他序列器子命令(除了 continue 之外)
--quit
:您可以忘记当前正在进行的操作。这可用于在 cherry-pick 或 revert 失败后清除序列器状态。--abort
:取消操作并返回到预序列状态。
以下是一些 cherry-picking 的示例
git cherry-pick master
:应用 master 分支顶端提交引入的更改,并使用此更改创建新提交git cherry-pick master~4 master~2
:应用 master 指向的倒数第五个和倒数第三个提交引入的更改,并使用这些更改创建两个新提交
感到不知所措?您无需记住所有命令。您始终可以在终端中键入 git cherry-pick --help
以查看更多选项或帮助。
3 条评论