我可以有多个暂存区或者使用git达到类似的效果吗?
我的典型工作流程沿着:
- 工作,工作,工作
- 现在我有了一个有用的想法,让我们提交它
git add -p
,y
,y
- 但首先是一些小的风格变化
git reset HEAD .
- 第一个四个一个x、第一个五个一个x、第一个六个一个x、第一个七个一个x、第一个八个一个x、第一个九个一个x
git add -p
..提交实际内容
有时候,我需要从一大堆修改中提交20个小的修改,如果我可以运行像git add -p
这样的补丁,然后将每个补丁“分派”到它自己的暂存区,并分别提交每个区域,这将保存我一天的时间。
2条答案
按热度按时间jm81lzqq1#
编辑,2020年5月30日:在Git 2.15或更高版本中,我建议使用
git worktree
,而不要尝试下面的操作。对于添加的工作树有一些限制,这使得它们在这种工作流中有点烦人,但它 * 可以 * 工作,并且内置在现代Git中。请注意,如果你做了我下面描述的事情,
git gc
就不会知道要检查你的备用索引文件,事实上,从Git 2.5最初引入到Git 2.15中修复,git gc
都忘记检查添加的工作树及其索引文件了!更多信息请参见VonC's answer。
事实上,在git中你可以有多个不同的暂存区(更确切地说,是多个索引文件),为了达到你想要的效果,无论如何你都必须编写自己的
git add -p
变体,所以我在这里要做的是勾画一个大纲,可以说是如何做到这一点。默认的索引文件--如果你不把它指向其他索引文件,git会使用它--位于
.git/index
(或者,更准确地说,shell是$GIT_DIR/.index
,$GIT_DIR
取自环境,如果没有设置,则取自git rev-parse --git-dir
)。但是如果你设置了环境变量
GIT_INDEX_FILE
,git会使用该文件作为索引,因此,你可以这样开始你的“分散修改到四个分支”过程:对于标为“困难部分”的部分,你最好的选择是复制git的add-interactive perl脚本,在
$(git --exec-path)/git-add--interactive
中找到,然后修改它以适应.要移除“恰好四次提交”的限制,让这个修改过的interactive-add动态地创建一个新的索引文件(通过复制原始的,或者创建一个等于HEAD
提交的“空”索引或其他什么;也参见X1 M11 N1 X)。编辑:some variation on 部分几乎肯定应该使用
git write-tree
和git commit-tree
从这些提交中创建 new branches,使用当前提交的父提交作为它们的父提交,而不是允许git commit
将这些提交串成一个线性链,这意味着还必须为这些新创建的分支选择一些命名方案。63lcw9qa2#
Git 2.5 introduced git worktree,它允许一个克隆,多个工作树,在其中您可以隔离您的各种修改。
但是现在(2019年第四季度),你不能再修改
git-add--interactive.perl
了,因为在Git 2.25(2020年第一季度)中,"git add -i
"已经被扩展到了"patch
"之外的子命令。(That重写在Git 2.37,Q3 2022中正式完成并设置为默认值(见上一节)。
请参见第Johannes Schindelin (
dscho
)页的第commit 2e697ce页、第commit d763357页、第commit 8746e07页、第commit ab1e1cc页、第commit c54ef5e页、第commit a8c45be页、第commit f37c226页、第commit c08171d页、第commit 0c3944a页(2019年11月29日)。(由Junio C Hamano --
gitster
--合并至commit 3beff38,2019年12月16日)built-in add -i
:执行patch
命令签署人:约翰内斯·申德林
当然,它还不是一个完整的实现,为了使它易于检查(并且易于防止bug),我们仍然将实际工作交给Perl脚本。
patch
的功能实际上占了git-add--interactive.perl
的1,800多行代码的一半以上,稍后将逐步从Perl移植到C。还是在用C语言重写git add的上下文中:更多测试覆盖率更新,为"
git add -i
"的进一步工作做准备。请参见第一版第十四页、第一版第十五页、第一版第十六页、第一版第十七页、第一版第十八页、第一版第十九页、第一版第二十页(2019年12月6日)。
(由Junio C Hamano --
gitster
--合并至commit 011fc2e,2019年12月16日)git add -p
:当diff生成失败时使用非零退出代码签署人:约翰内斯·申德林
git add -p
做的第一件事是生成一个diff,如果不能生成这个diff,git add -p
就不应该像什么都没发生一样继续,而是失败。我们在这里 * 实际 * 做的事情要广泛得多:我们现在针对 * 每个 *
run_cmd_pipe()
调用验证所产生的进程实际上成功。请注意,我们必须更改此补丁中的两个调用程序,因为我们需要将派生进程的输出存储在一个局部变量中,这意味着调用程序无法再决定是在数组还是标量上下文中解释
return <$fh>
。在为diff. algorithm特性编写测试用例时注意到了这个bug,我们也将该测试用例作为这个已修复bug的回归测试。
随着Git 2.25(2020年第一季度)的发布,将"
git-add--interactive
"迁移到C语言的努力仍在继续。请参见commit 2e40831、commit 54d9d9b、commit ade246e、commit d6cf873、commit 9254bdf、commit bcdd297、commit b38dd9e、commit 11f2c0d、commit 510aeca、commit 0ecd9d2、commit 5906d5d、commit 47dc4fd、commit 80399ae、commit 7584dd3、commit 12c24cf、commit 25ea47a、commit e3bd11b、第一年第四十二次、第一年第四十三次(2019年12月13日)和第一年第四十四次。
(由Junio C Hamano --
gitster
--合并至commit 45b96a6,2019年12月25日)built-in add -p
:实现块编辑签署人:约翰内斯·申德林
就像
git add --edit
允许用户在应用到索引之前编辑diff一样,这个特性允许用户编辑diff * hunk *。当然,这里会变得有点复杂,因为结果必须与整个diff的剩余块很好地匹配。因此,我们必须做一个循环,让用户编辑块,然后测试结果是否有效,如果无效,则放弃编辑,让用户决定是否再次尝试编辑块。
注:与Perl版本不同,我们也使用相同的diff "coalescing"(即将重叠的块合并为一个)来进行编辑后的检查,并且我们为此引入了一个新的标志,要求
reassemble_patch()
函数假装所有块都被选中使用。这允许我们继续运行
git apply
* 而不使用 *--allow-overlap
选项(与Perl版本不同),并且它还修复了t3701-add-interactive.sh
中的两个已知的损坏(到目前为止,我们还不能将其标记为已解决,因为Perl脚本版本仍然是默认版本,并且仍然存在这些损坏)。以及:
built-in add -p
:分裂后合并块签署人:约翰内斯·申德林
这被认为是"正确的做法",根据933e44d3a0("
add -p
":解决一个老的懒惰,不合并大块,2011 - 04 - 06,Git v1.7.5.2).注意:我们不能在合并的时候简单地修改块;一旦我们实现了块体编辑,每当块体被编辑时,我们将调用
reassemble_patch()
,因此我们不能修改块体(因为用户可能会点击K
并改变他们是否暂存前一个块体的想法)。以及:
built-in add -i
:开始在C中实现patch
功能签署人:约翰内斯·申德林
在前面的步骤中,我们用C语言重新实现了
git add -i
的主循环以及大多数命令。值得注意的是,我们忽略了
patch
的实际功能,因为相关代码占git-add--interactive.perl
的一半以上,并且实际上与其余命令非常独立。有了这个提交,我们开始处理
patch
部分。为了更好地分离关注点,我们将代码保存在一个单独的文件add-patch.c
中。新代码仍然被保护在add.interactive.useBuiltin
配置设置后面,目前,它只能通过git add -p
调用。实际功能遵循5cde71d64aff的原始实现("
git add --interactive
",2006年12月10日,Git v1.5.0-rc0--merge),但不要太接近(例如,我们使用字符串偏移而不是到处复制字符串,并且在查看k
和j
命令是否适用之后,在C版本中,我们会记住前一个/下一个块未决定,并使用它,而不是在用户要求跳转时再次查看)。作为对该提交的进一步改进,我们还使用逗号而不是斜杠来分隔提示符中的可用命令,正如Perl脚本的当前版本所做的那样,并且我们还在帮助文本中添加了一行关于问号的内容("print help")。
虽然很容易将
git add -p
的这种转换用作在apply_all_patches()
上工作的借口,以便它 * 不 * 希望从stdin
或从文件读取文件,而是接受(比如说)strbuf
,但我们将在此阶段避免这种特殊的兔子洞。重写工作的结论可以在Git 2.29(Q4 2020)中找到:"
add -i
/-p
"机制已用C编写,但尚未默认使用。默认为参与**
feature.experimental
**实验的人员。参见Junio C Hamano (
gitster
)(2020年9月8日)。(由Junio C Hamano --
gitster
--合并至commit e96b271,2020年9月18日)add -i
:当设置feature.experimental
时使用内置版本确认人:Johannes Schindelin
我们从2.25开始就有了"
add -i
/-p
"的并行实现,并且从2.26开始就在各种代码路径中使用它们,但是从来没有把内置版本作为默认版本。我们已经发现并修复了内置版本中的一些极端错误,现在可能是开始将用户群从脚本版本切换到内置版本的好时机。
让我们为那些选择加入
feature.experimental
guinea-pig计划的人启用内置版本,以获得更广泛的曝光。而且,在Git 2.29(2020年第四季度)中,仍然有一个"
add -i
/-p
"修复:参见commit 1c6ffb5、commit dc62641(2020年9月7日)。
(由Junio C Hamano --
gitster
--合并至commit 694e517,2020年9月18日)add-patch
:修复了repo_read_index()
的反向返回代码签署人:杰夫·金
确认人:Johannes Schindelin
在将块应用到带有"
add -p
"的文件之后,Cpatch_update_file()
函数尝试刷新索引(就像Perl版本所做的那样)。我们只能在能够读入索引的情况下刷新索引,因此我们首先检查
repo_read_index()
的返回值。但与许多函数不同的是,"0"表示成功,该函数被记录为返回索引中的条目数。
因此,我们应该用一个非负的返回值来检查是否成功。
测试和任何用户似乎都没有注意到这一点,可能是由于以下因素的组合:
git diff
"(man)或"git commit
",将自动刷新索引。但是您可以通过在"
add -p
"暂存所有块之后立即运行管道"git diff-files
"(man)来查看问题。使用GIT_TEST_ADD_I_USE_BUILTIN=1
运行新测试失败,没有匹配的代码更改。在Git 2.37(2022年第三季度)中,"
git add -i
"(man)在一段时间前用C重写,并一直在测试中;重新实现现在默认情况下向公众公开。参见Johannes Schindelin (
dscho
)的commit 0527ccb、commit ed922dc(2021年11月30日)。(2022年5月30日由Junio C Hamano --
gitster
--合并到commit 1fc1879)add -i
:默认为内置实现签署人:约翰内斯·申德林
在9a5315e中("合并分支'js/patch-mode-in-others-in-c'",2020 - 02 - 05,Git v2.26.0-rc0--merge,列在batch #3中),Git获得了
git add
(man)交互模式的内置实现,可以通过配置选项add.interactive.useBuiltin
打开。第一个支持这个旋钮的官方Git版本是v2.26.0。
在2df2d81("添加-i:设置了feature. experimental时使用内置版本",2020年9月8日,Git v2.29.0-rc0--merge列于batch #15中),此内置实现也通过
feature.experimental
启用。包含此变更的第一个版本是v2.29.0。
一年多以后(很少有bug报告),是时候宣布内置实现成熟并默认打开它了。
我们特意保留了
add.interactive.useBuiltin
配置,以便用户在意外情况下遇到以前未检测到的bug时可以使用"逃生出口"。git config
现在在其手册页中包括:设置为
false
将回退到交互式版本git add
的原始Perl实现,而不是内置版本。true
**。随着Git 2.40(2023年第一季度)的发布,最终淘汰了脚本化的"
git add
"(man)-p/- i实现,让大家使用用C重新实现的那个。参见Ævar Arnfjörð Bjarmason (
avar
)的commit 5a7d41d、commit d21878f、commit 20b813d(2023年2月6日)。(由Junio C Hamano --
gitster
--合并到commit 06bca97,2023年2月15日)add
:删除"添加.交互. useBuiltin"& Perl "git添加--交互"签署人:埃瓦尔·阿恩菲约德·比亚尔马森
由于commit 0527ccb(
add -i
:默认为内置实现,2021年11月30日,Git v2.37.0-rc0--batch #5中列出的merge)(add -i
:默认为内置实现,Git v2.37.0首次发布时,默认为内置版本"add -i
"。该内置实现被添加到commit f83dff6中(开始实现
git add --interactive
的内置版本,2019 - 11 - 13,Git v2.25.0-rc0--merge列在batch #3中)(开始实现git add
的内置版本(man),首次随Git v2.25.0发布。现在已经有足够的时间来查找这个新实现中的任何剩余bug,所以让我们删除后备代码。
git config
现在在其手册页中包括:add.interactive.useBuiltin
未使用的配置变量。
在Git v2.25.0到v2.36.0版本中使用,以启用内置版本
git add
的交互模式,该模式随后成为Git v2.37.0到v2.39.0版本的默认模式。