多个临时区域

时间:2015-03-09 16:35:43

标签: git

我可以使用git进行多个临时区域或达到类似的效果吗?

我的典型工作流程如下:

  • 工作,工作,工作
  • 现在我知道有用的东西,让我们提交git add -pyy
  • 但首先是这些较小的样式更改:git reset HEAD .
  • git add -pnnyqgit commit -m "style changes"
  • git add -p ..提交实际内容

有时我会从一大堆变化中做出20次较小的提交。如果我可以运行像git add -p这样的补丁,然后将每个补丁“分派”到它自己的暂存区域并分别提交每个区域,那么每天可以节省数小时。

2 个答案:

答案 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-treegit 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 2e697cecommit d763357commit 8746e07commit ab1e1cccommit c54ef5ecommit a8c45becommit 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 -icommit b4bbbbdcommit 89c8559commit e91162bcommit 0c3222ccommit 24be352commit 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 -pcommit 2e40831commit 54d9d9bcommit ade246ecommit d6cf873commit 9254bdfcommit bcdd297,{{3} },commit b38dd9ecommit 11f2c0dcommit 510aecacommit 0ecd9d2commit 5906d5dcommit 47dc4fdcommit 80399aecommit 7584dd3commit 12c24cfcommit 25ea47acommit e3bd11bcommit 1942ee4(2019年12月13日)。
(由commit f6aa7ecJohannes 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 -pk命令是否适用之后,在C版本中,我们记得尚未决定使用哪个前一个/下一个块。而不是在用户要求跳转时再次查看)。

     

作为与该提交的进一步偏离,我们还使用逗号而不是斜杠来分隔提示符中的可用命令,因为当前版本的Perl脚本会这样做,并且还添加了一个关于问号的行(“打印帮助”)添加到帮助文本。

     

虽然很诱人以j的这种转换为借口git add -p的借口,但它不是想要从{{1}读取文件}或文件中,但是接受apply_all_patches()这样的名称,那么在此阶段,我们将避免使用该特定的兔子洞。