我可以使用git进行多个临时区域或达到类似的效果吗?
我的典型工作流程如下:
git add -p
,y
,y
git reset HEAD .
git add -p
,n
,n
,y
,q
,git commit -m "style changes"
git add -p
..提交实际内容有时我会从一大堆变化中做出20次较小的提交。如果我可以运行像git add -p
这样的补丁,然后将每个补丁“分派”到它自己的暂存区域并分别提交每个区域,那么每天可以节省数小时。
答案 0 :(得分:11)
实际上,你可以在git中有多个不同的临时区域(更多字面意思,多个索引文件)。为了达到你想要的效果,无论如何你都必须编写自己的git add -p
变体,所以我在这里要做的是勾勒出如何做到这一点的轮廓。
默认索引文件 - 如果你没有将它引导到其他索引文件,那么git就会使用.git/index
(或者更正确,$GIT_DIR/.index
$GIT_DIR
}取自环境,如果没有设置,则取自git rev-parse --git-dir
)。
但是,如果设置环境变量GIT_INDEX_FILE
,git将使用该文件作为索引。因此,您可以通过执行以下操作来开始“分散更改为四个分支”过程:
GIT_DIR=${GIT_DIR:-$(git rev-parse --git-dir)} || exit 1
index_tmp_dir=$(mktemp -d) || exit 1
trap "rm -rf $index_tmp_dir" 0 1 2 3 15 # clean up on exit
# make four copies of initial staging area
for f in i1 i2 i3 i4; do
cp $GIT_DIR/index $index_tmp_dir/$f
done
# THIS IS THE HARD PART:
# Now, using `git diff-files -p` or similar, get patches
# (diff hunks).
# Whenever you're ready to stage one, pick an index for it,
# then use:
GIT_INDEX_FILE=$index_tmp_dir/$which git apply --cached < diffhunk
# Once done, commit each index file separately with some
# variation on:
for f in i1 i2 i3 i4; do
GIT_INDEX_FILE=$index_tmp_dir/$which git commit
done
对于标有“硬件”的部分,最好的选择可能是复制git的add-interactive perl脚本,在$(git --exec-path)/git-add--interactive
中找到,然后修改它以适应。要删除“正好四个提交”限制,请使此修改后的interactive-add动态创建一个新的索引文件(通过复制原始文件,或者创建一个等于HEAD
提交的“空”索引或其他;请参阅{ {1}}也是如此。
编辑:部分的部分变体几乎肯定应该使用git read-tree
和git write-tree
从每个提交中生成新分支 ,使用当前提交的父级作为其父级,而不是允许git commit-tree
将提交串联为一个线性链。这意味着还必须为这些新创建的分支选择一些命名方案。
答案 1 :(得分:0)
Git 2.5 introduced git worktree于2015年7月发布,它允许一个克隆,多个工作树,您可以在其中隔离各种修改。
但是,如今(2019年第四季度),您将无法再长时间修改git-add--interactive.perl
,因为在Git 2.25(2020年第一季度)中,“ git add -i
”已经用C语言重写了。 ,已扩展为涵盖“ patch
”以外的子命令。
请参见commit 2e697ce,commit d763357,commit 8746e07,commit ab1e1cc,commit c54ef5e,commit a8c45be,commit f37c226,{{3} },commit c08171d(2019年11月29日)通过commit 0c3944a。
(由Johannes Schindelin (dscho
)在Junio C Hamano -- gitster
--中合并,2019年12月16日)
commit 3beff38:实施
patch
命令签名人:Johannes Schindelin
嗯,这还不是一个完整的实现。为了使它易于检查(并易于排除错误),我们仍然使用Perl脚本来完成实际工作。
patch
功能实际上占git-add--interactive.perl
的1,800多行中的一半以上。稍后,它将逐步从Perl移植到C。
仍然在C语言中重写git add的上下文中:更新了更多的测试覆盖率,以准备进一步研究“ git add -i
”。
请参见built-in add -i
,commit b4bbbbd,commit 89c8559,commit e91162b,commit 0c3222c,commit 24be352,commit 8539b46(2019年12月6日)由commit 0f0fba2。
(由Johannes Schindelin (dscho
)在Junio C Hamano -- gitster
--中合并,2019年12月16日)
commit 011fc2e:在差异生成失败时使用非零退出代码
签名人:Johannes Schindelin
git add -p
做的第一件事是生成差异。如果无法生成此差异,则git add -p
不应继续进行,好像什么也没发生,而是失败。我们实际上 所做的事情要广泛得多:现在,我们为每个
run_cmd_pipe()
调用验证产生的过程实际上已经成功。请注意,我们必须在此补丁中更改两个调用者,因为我们需要将生成的进程的输出存储在局部变量中,这意味着调用者无法再决定是否解释数组中的
return <$fh>
或在标量环境中。在为diff.algorithm功能编写测试用例时注意到了该错误,我们也将该测试用例用作此固定错误的回归测试。
借助Git 2.25(2020年第一季度),继续将“ git-add--interactive
”移至C的努力。
请参见git add -p
,commit 2e40831,commit 54d9d9b,commit ade246e,commit d6cf873,commit 9254bdf,commit bcdd297,{{3} },commit b38dd9e,commit 11f2c0d,commit 510aeca,commit 0ecd9d2,commit 5906d5d,commit 47dc4fd,commit 80399ae,commit 7584dd3, commit 12c24cf的commit 25ea47a,commit e3bd11b,commit 1942ee4(2019年12月13日)。
(由commit f6aa7ec在Johannes Schindelin (dscho
)中合并,2019年12月25日)
Junio C Hamano --
gitster
--:实现大块编辑签名人:Johannes Schindelin
就像
git add --edit
一样,它允许用户在将差异应用到索引之前对其进行编辑,此功能使用户可以编辑差异 hunk 。自然地,它在这里变得更加复杂,因为结果必须与整体差异的其余部分相吻合。因此,我们必须做一个循环,让用户编辑大块,然后测试结果是否可行,如果不行,则放弃编辑,让用户决定是否再次尝试编辑大块。
注意:与Perl版本相反,我们在编辑后也使用相同的diff“合并”(即,将重叠的大块合并为一个),并且为此引入了一个新标记,要求{1}}的作用是假装所有帅哥都已选择使用。
这使我们能够继续运行
reassemble_patch()
而没有git apply
选项(与Perl版本不同),并且还修复了--allow-overlap
中的两个已知的破损(到目前为止,我们无法将其标记为已解决,因为Perl脚本版本仍是默认版本,并且仍然存在这些缺陷)。
并且:
commit 45b96a6:将大块分割后合并在一起
签名人:Johannes Schindelin
根据
built-in add -p
(“t3701-add-interactive.sh
”,这被认为是“正确的做法”:解决旧的懒惰并不能合并帅哥,2011-04-06,Git v1 .7.5.2)。注意:我们不能在合并它们的同时简单地修改它们。实施大块编辑后,每当编辑大块时,我们都会调用
add -p
,因此我们绝不能修改大块(因为用户可能会打reassemble_patch()
,并且改变主意是否准备上一个大块)
并且:
built-in add -p
:开始在C中实现K
功能签名人:Johannes Schindelin
在前面的步骤中,我们在C中重新实现了
patch
的主循环以及大多数命令。值得注意的是,我们省略了
git add -i
的实际功能,因为相关代码占patch
的一半以上,并且实际上与其余命令无关。通过此提交,我们开始处理
git-add--interactive.perl
部分。为了更好地分离问题,我们将代码保存在单独的文件933e44d3a0中。新代码仍受patch
配置设置的保护,目前只能通过add.interactive.useBuiltin
调用。实际功能遵循
built-in add -i
(“add-patch.c
”,2006-12-10,Git v1.5.0-rc0-5cde71d64aff)的原始实现,但并不太紧密(例如,我们使用字符串偏移量而不是在字符串周围复制字符串,并且在查看git add -p
和k
命令是否适用之后,在C版本中,我们记得尚未决定使用哪个前一个/下一个块。而不是在用户要求跳转时再次查看)。作为与该提交的进一步偏离,我们还使用逗号而不是斜杠来分隔提示符中的可用命令,因为当前版本的Perl脚本会这样做,并且还添加了一个关于问号的行(“打印帮助”)添加到帮助文本。
虽然很诱人以
j
的这种转换为借口git add -p
的借口,但它不是想要从{{1}读取文件}或文件中,但是接受apply_all_patches()
这样的名称,那么在此阶段,我们将避免使用该特定的兔子洞。