Git扩展笔记

642 阅读6分钟

git-cherry-pick

(官方文档的解释): 给定一个或多个现有提交,应用每个引入的更改,并记录每个提交的新提交

如果不清楚如何应用更改,则会发生以下情况:

  • 当前分支和指针HEAD保留在最后一次成功提交上。
  • 引用CHERRY_PICK_HEAD设置为指向引入了难以应用的更改的提交。
  • 正确应用更改的路径在索引文件及其工作树中更新。
  • 对于冲突的路径,索引文件最多注册三个版本,如git-merge [1]的“ TRUE MERGE”部分所述。工作树文件将包括对常见冲突标记<和冲突的描述>。

git-cherry-pick的选件

  • commit:可以传递提交集,但是默认情况下不会遍历提交
  • -e --edit: 使用此选项,git cherry-pick将允许您在提交之前编辑提交消息
  • --cleanup=:此选项确定的提交信息将被传递到之前清理提交
  • -x:在记录提交时,请在原始提交消息后添加一行,以表明此更改是从哪个提交中挑选出来的
  • -r:该命令默认执行-x 上述操作,并且-r被禁用。现在默认为不操作,-x因此此选项为无操作。
  • -m parent-number --mainline parent-number:通常,您无法选择合并,因为您不知道合并的哪一侧应被视为主线。此选项指定主线的父代号(从1开始),并允许cherry-pick重播相对于指定父代的更改
  • -n --no-commit:该命令会自动创建一系列提交。该标志将必要的更改应用到选择每个命名提交的工作树和索引中,而不进行任何提交
  • -s --signoff:在提交消息的末尾添加“按行签名”
  • -S[] --gpg-sign[=]:GPG签名提交。该keyid参数是可选的,默认为提交者身份。如果指定,则必须将其固定在选项中,且不能留空格
  • --ff:如果当前HEAD与Cherry-pick提交的提交的父级相同,则将快速执行此提交。
  • --allow-empty:默认情况下,挑选一个空的提交失败,这表明需要显式调用git commit --allow-empty。此选项将覆盖该行为,从而允许空提交自动保留在“自动选择”中。请注意,当“ --ff”生效时,即使没有此选项,也将保留符合“快进”要求的空提交。还要注意,使用此选项只会保留最初为空的提交(即,提交记录的树与其父树相同)。由于先前的提交而变为空的提交将被删除
  • --allow-empty-message:默认情况下,挑选带有空消息的提交将失败。此选项将覆盖该行为,从而允许选择带有空消息的提交
  • --keep-redundant-commits:如果被挑选的提交与当前历史记录中已有的提交重复,则它将变为空。默认情况下,这些多余的提交导致cherry-pick停止,因此用户可以检查该提交。此选项将覆盖该行为并创建一个空的提交对象
  • --strategy=:使用给定的合并strategy 只能使用一次
  • -X --strategy-option=:将特定于合并策略的选项传递到合并策略
  • --rerere-autoupdate --no-rerere-autoupdate:如果可能,允许rerere机制使用自动冲突解决的结果来更新索引

排序子命令

  • --continue:在解决失败的cherry-pick选择或还原中的冲突后,可用于继续操作。
  • --skip:跳过当前提交并继续执行其余的序列
  • --quit:放弃当前正在进行的操作,可以清除排序器的状态
  • --abort:取消操作并返回到先序状态

小书中对git-cherry-pick的解释:

git cherry-pick 命令用来获得在单个提交中引入的变更,然后尝试将作为一个新的提交引入到当前分支上。 从一个分支单独一个或者两个提交而不是合并整个分支的所有变更是非常有用的。

git merge

官方文档中对git merge的解释:

将两个或多个开发历史结合在一起

将命名提交中的更改(自其历史记录与当前分支分开以来的时间)合并到当前分支中。git pull使用此命令来合并来自另一个存储库的更改,并且可以手动使用它来将一个分支中的更改合并到另一个分支中

merge的选件

  • -commit --no-commit: 执行合并并提交结果。此选项可用于覆盖--no-commit 使用--no-commit可以在创建合并提交之前执行合并和停止操作,从而使用户有机会在提交之前检查并进一步调整合并结果
  • --edit -e --no-edit:提交成功的merge合并之前,请调用编辑器以进一步编辑自动生成的合并消息,以便用户可以解释并证明合并的合理性
  • --cleanup=:此选项确定在提交之前如何清除合并消息
  • --ff --no-ff --ff-only:指定当合并的历史记录已经是当前历史记录的后代时,如何处理合并 使用--ff,尽可能将合并解析为快进(仅更新分支指针以匹配合并的分支;不创建合并提交) 使用--no-ff,即使在合并可以替代为快进的情况下,在所有情况下都可以创建合并提交 使用--ff-only,在可能的情况下将合并解析为快进。如果不可能,请拒绝合并并以非零状态退出
  • -S[] --gpg-sign[=]:GPG对结果合并提交签名。该keyid参数是可选的,默认为提交者身份。如果指定,则必须将其固定在选项中,且不能留空格
  • --log[=]:除了分支名称之外,还使用最多来自正在合并的个实际提交的单行描述填充日志消息 --no-log:使用--no-log不会列出正在合并的实际提交中的单行描述
  • --signoff --no-signoff:在提交日志消息的末尾添加由提交者签名的行。签名的含义取决于项目,但是通常可以证明提交者有权按照相同的许可证提交此作品,并同意开发者原产地证书 使用--no-signoff时,不添加“按行签名”
  • --stat -n --no-stat: 在合并结束时显示diffstat diffstat也由配置选项merge.stat控制 使用-n或--no-stat在合并结束时不显示diffstat
  • --squash --no-squash:产生工作树和索引状态,就好像发生真正的合并一样,但实际上不进行提交,移动HEAD或记录$GIT_DIR/MERGE_HEAD (以使下一个git commit命令创建合并提交 这使您可以在当前分支的顶部创建一个提交,其作用与合并另一个分支的作用相同 使用--no-squash执行合并并提交结果 此选项可用于覆盖--squash 使用--squash时,--commit是不允许的,并且会失败
  • --no-verify:此选项绕过pre-merge和commit-msg挂钩
  • -s --strategy=:使用给定的合并策略;可以多次提供,以按应尝试的顺序指定它们。如果没有-s选项,则使用内置策略列表代替(合并单个头部时为git merge-recursive,否则为git merge-octopus)
  • -X --strategy-option=:将特定于合并策略的选项传递到合并策略
  • --verify-signatures --no-verify-signatures:验证是否使用有效密钥(即具有有效uid的密钥)对要合并的侧分支的尖端提交进行了签名:在默认信任模型中,这意味着签名密钥已由可信密钥签名。如果未使用有效密钥对侧分支的尖端提交进行签名,则合并将中止
  • -m :设置要用于合并提交的提交消息 如果--log指定,则将合并的提交的简短日志附加到指定的消息
  • -F --file=:读取要用于合并提交的提交消息 如果--log指定,则将合并的提交的简短日志附加到指定的消息
  • --overwrite-ignore --no-overwrite-ignore:从合并结果中静默覆盖被忽略的文件 使用--no-overwrite-ignore中止
  • --abort:中止当前的冲突解决过程,并尝试重构合并前状态
  • --quit:放弃当前正在进行的合并 保持索引和工作树不变
  • --continue:由于冲突而停止git合并后,您可以通过运行git merge --continue结束合并
  • :合并到分支中 指定一个以上提交将与两个以上的父级创建一个合并

合并前检查

当本地未提交的更改与git pull / git merge可能需要更新的文件重叠时,git pull和git merge将停止而不进行任何操作 为了避免在合并提交中记录无关的更改,如果在索引中注册了与提交有关的任何更改,则 git pull和git merge也将中止HEAD 如果所有已命名的提交都已经是上级的HEAD,则git merge 将提前退出,并显示消息“Already up to date”

快进合并

当前分支头通常是指定提交的上级,在这种情况下,不需要新的提交来存储组合的历史记录;而是HEAD(连同索引)被更新为指向指定的提交,而不创建额外的合并提交。 使用--no-ff选项可以停止此行为。

TRUE MERGE

提交了一个合并版本,该版本协调了要合并的所有分支的更改,并且HEAD,索引和工作树也已更新到该版本 只要修改不重叠,就有可能在工作树中进行修改。更新将保留它们

如果不清楚如何协调更改,则会发生以下情况:

  • 该HEAD指针保持不变。
  • 该MERGE_HEADRef设定点到另一个分支头。
  • 干净合并的路径会在索引文件和工作树中同时更新。
  • 对于冲突的路径,索引文件记录多达三个版本:1个存储从共同的上级,从第2阶段的版本HEAD,和第三阶段从MERGE_HEAD(你可以检查阶段git ls-files -u)。工作树文件包含“合并”程序的结果;即与熟悉的冲突标记的三路合并结果<<< === >>>。
  • 没有其他更改。特别是,您在开始合并之前进行的本地修改将保持不变,并且它们的索引条目保持不变,即match HEAD。

如果您尝试进行合并而导致复杂的冲突并希望重新开始,则可以使用恢复git merge --abort。

合并标签

合并带注释(且可能已签名)的标签时,即使可能进行快速合并,Git也会始终创建合并提交,并且使用标签消息准备提交消息模板。此外,如果标记已签名,则签名检查将作为注释报告在消息模板中

在这种情况下,您可以在将标签提供给之前自己“解开”标签git merge,或者--ff-only在您自己没有任何工作时通过 示例如下:

git fetch origin 
git merge v1.2.3 ^ 0 
git merge --ff-only v1.2.3

合并机制

git merge和git pull命令 允许使用option 选择后端合并策略-s。一些策略也可以采取自己的选择,可以通过给和和或作为-X 参数来传递它们。git mergegit pull

组态

  • merge.conflictStyle 指定在合并时将冲突的块块写出到工作树文件中的样式。
  • merge.defaultToUpstream 如果在没有任何提交参数的情况下调用merge,请使用存储在其远程跟踪分支中的最后观察值来合并为当前分支配置的上游分支。
  • merge.ff 默认情况下,当合并作为当前提交的后代的提交时,Git不会创建额外的合并提交。相反,当前分支的尖端是快进的。设置false为时,此变量告诉Git在这种情况下创建一个额外的合并提交(相当于--no-ff从命令行提供选项)。设置only为时,仅允许这种快速合并(等同于--ff-only从命令行提供选项)。
  • merge.verifySignatures 如果为true,则等效于--verify-signatures命令行选项。
  • merge.branchdesc 除了分支名称之外,还使用与之关联的分支描述文本填充日志消息。默认为false。
  • merge.log 除了分支名称之外,最多还使用来自正在合并的实际提交的指定数量的单行描述填充日志消息。默认为false,true为20的同义词。
  • merge.renameLimit 合并期间执行重命名检测时要考虑的文件数;如果未指定,则默认为diff.renameLimit的值。如果关闭重命名检测,则该设置无效。
  • merge.renames Git是否检测到重命名。如果设置为“ false”,则禁用重命名检测。如果设置为“ true”,则启用基本的重命名检测。默认为diff.renames的值。
  • merge.directory重命名 Git检测到目录是否重命名。如果将merge.directoryRenames设置为“ false”,则禁用目录重命名检测,这意味着这些新文件将留在旧目录中。如果设置为“ true”,则启用目录重命名检测,这意味着此类新文件将被移动到新目录中
  • merge.stat 在合并结束时是否在ORIG_HEAD和合并结果之间打印diffstat。默认为True

小书中的解释:

你可以运行你的测试,确保你的修改是正确的,然后将其合并回你的 master 分支来部署到线上。 你可以使用git merge 命令来达到上述目的:

示例如下:

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

submodules

官方文档对 submodules的解释:

通常,在处理一个项目时,您需要从其中使用另一个项目 Git使用子模块解决了子模块允许将Git存储库保留为另一个Git存储库的子目录。这可以将另一个存储库克隆到项目中,并使提交分开进行

小书中的解释:

在 发布子模块改动 一节中,我们使用 --recurse-submodules 选项来检查是否我们所有的子模块的工作都已 经在推送子项目之前已经推送出去了

Git 在推送到主项目前检查所有子模块是否已推送。 git push 命令接受可以设 置为 “check” 或 “on-demand” 的 --recurse-submodules 参数。 如果任何提交的子模块改动没有推送 那么 “check” 选项会直接使 push 操作失败