多个临时区域

Tho*_*sen 30 git

我可以使用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,然后将每个补丁"发送"到它自己的暂存区域并分别提交每个区域.

tor*_*rek 12

事实上,你可以在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
Run Code Online (Sandbox Code Playgroud)

对于标记为"硬件"的部分,最好的选择可能是复制git的add-interactive perl脚本,找到$(git --exec-path)/git-add--interactive它,然后修改它以适应.要删除"正好四个提交"限制,请使此修改后的interactive-add动态创建一个新的索引文件(通过复制原始文件,或者创建一个等于HEAD提交或其他的"空"索引;另请参阅git read-tree).

编辑:部分的一些变化几乎肯定应该使用git write-tree并从每个提交中git commit-tree创建新的分支,使用当前提交的父级作为其父级,而不是允许git commit将提交串联为一个线性链.这意味着还必须为这些新创建的分支选择一些命名方案.

  • @ThomasJensen,imo这个工作流程是唯一理智的工作流程.在*独占*离散逻辑块上工作然后提交它们是不现实的.你进入流程,因为你正在处理一个文件而你注意到其他东西,可能就像需要删除的旧注释一样简单.一个小时后,你的索引充满了不同的变化.能够通过它们" - 补丁",将每个更改切换到适当的逻辑块,正是您大多数时候想要的.令人震惊的是它没有在功能上烘焙. (13认同)
  • 这正是我一直在寻找的结果,我很惊讶至少有一个众所周知的第三方解决方案并不常见.是关于我的工作流程被打破了吗? (6认同)
  • 相同.这需要适当的解决方案.我无法为我的生活摆脱这种工作方式! (3认同)
  • 我不一定会说"破碎"和"不寻常"一样多.而且,并不是说我会在它上面取得任何巨大的成功,但是我尝试做的是做出很多微小的提交,无论是对于"手头的主要任务"还是(单独的提交,但在相同的临时分支上)都是小方面修复,然后我可以通过`git cherry-pick`拆分成不同的分支(然后清理或丢弃所有小提交的分支).(你说的方法更多是簿记等) (2认同)

Von*_*onC 6

Git 2.5 于 2015 年 7 月引入了 git worktree,它允许一个克隆、多个工作树,您可以在其中隔离您的各种修改。

\n

但现在(2019 年第 4 季度),您将无法修改git-add--interactive.perl太久,因为在 Git 2.25(2020 年第 1 季度)中,用git add -iC 重写的“”已扩展到涵盖“ patch”以外的子命令。

\n

(该重写已正式完成,并在 2022 年第 3 季度的 Git 2.37 中默认。请参阅最后一节)。

\n

请参阅提交 2e697ce提交 d763357提交 8746e07提交 ab1e1cc提交 c54ef5e提交 a8c45be提交 f37c226提交 c08171d提交 0c3944a(2019 年 11 月 29 日),作者:Johannes Schindelin ( dscho)
\n (由Junio C Hamano 合并 -- gitster--提交 3beff38中,2019 年 12 月 16 日)

\n
\n

built-in add -i:执行patch命令

\n

签署人:约翰内斯·辛德林

\n

嗯,它还没有完全实施。为了使其易于审查(并且易于排除错误),我们仍然将实际工作交给 Perl 脚本来完成。

\n

patch功能实际上占了 1,800 多行代码的一半以上git-add--interactive.perl。稍后它将逐步从 Perl 移植到 C。

\n
\n

仍在 C 中重写 git add 的背景下:更多测试覆盖率更新,为“ git add -i”的进一步工作做准备。

\n

请参阅提交 b4bbbbd提交 89c8559提交 e91162b提交 0c3222c提交 24be352提交 8539b46提交 0f0fba2(2019 年 12 月 6 日),作者:Johannes Schindelin ( dscho)
\n (由Junio C Hamano 合并 -- gitster--提交 011fc2e中,2019 年 12 月 16 日)

\n
\n

git add -p:当 diff 生成失败时使用非零退出代码

\n

签署人:约翰内斯·辛德林

\n

首先git add -p要做的就是生成差异。如果无法生成此差异,git add -p则不应像什么都没发生一样继续,而是失败。

\n

我们在这里实际做的事情要广泛得多:我们现在验证每个 run_cmd_pipe()调用所生成的进程是否确实成功。

\n

请注意,我们必须更改此补丁中的两个调用者,因为我们需要将生成的进程的输出存储在本地变量中,这意味着调用者无法再决定是解释数组return <$fh>还是标量上下文。

\n

在为 diff.algorithm 功能编写测试用例时注意到了这个错误,我们也让该测试用例兼作此修复错误的回归测试。

\n
\n
\n

在 Git 2.25(2020 年第一季度)中,将“ ”转移到 C 的努力git-add--interactive仍在继续。

\n

请参阅提交 2e40831提交 54d9d9b、提交ade246e、提交d6cf873、提交9254bdf、提交bcdd297、提交b38dd9e、提交 11f2c0d 、提交 510aeca 提交0ecd9d2提交 5906d5d提交 47dc4fd提交80399ae提交 7584dd3提交 12c24cf提交 25ea47a提交e3bd11b提交 1942ee4提交 f6aa7ec(2019 年 12 月 13 日),作者:Johannes Schindelin ( )。\n (由Junio C Hamano 合并 -- --提交 45b96a6中,2019 年 12 月 25 日)dscho
gitster

\n
\n

built-in add -p: 实现大块编辑

\n

签署人:约翰内斯·辛德林

\n

就像git add --edit允许用户在将 diff 应用到索引之前编辑 diff 一样,此功能允许用户编辑 diff hunk

\n

当然,这里会变得更加复杂,因为结果必须与整体差异的其余部分很好地配合。因此,我们必须做一个循环,让用户编辑该块,然后测试结果是否有效,如果不行,则放弃编辑并让用户决定是否再次尝试编辑该块。

\n

注意:与 Perl 版本相比,我们使用相同的 diff“合并”(即,将重叠的块合并为一个)来进行编辑后的检查,并且我们为此目的引入了一个新标志,要求函数reassemble_patch()假装所有帅哥都被选中使用。

\n

git apply 这允许我们在没有该选项的情况下继续运行--allow-overlap(与 Perl 版本不同),并且它还修复了两个已知的损坏t3701-add-interactive.sh(到目前为止我们无法将其标记为已解决,因为 Perl 脚本版本仍然是默认版本并且继续存在这些损坏) 。

\n
\n

和:

\n
\n

built-in add -p:将大块头分开后合并起来

\n

签署人:约翰内斯·辛德林

\n

根据933e44d3a0(“ add -p”:解决不合并帅哥的旧懒惰问题,2011-04-06,Git v1.7.5.2),这被认为是“正确的做法”。

\n

注意:我们不能在合并时简单地修改块;一旦我们实现了块编辑,reassemble_patch()每当编辑块时我们都会调用,因此我们不能修改块(因为用户可能会点击K并改变主意是否要上演前一个块)。

\n
\n

和:

\n
\n

built-in add -i: 开始实施patch用C实现功能

\n

签署人:约翰内斯·辛德林

\n

在前面的步骤中,我们重新实现了主循环git add -iC 语言的主循环以及大部分命令。

\n

值得注意的是,我们忽略了 的实际功能patch,因为相关代码占了一半以上git-add--interactive.perl,并且实际上非常独立于其余命令。

\n

通过这次提交,我们开始解决该patch部分。为了更好地分离关注点,我们将代码保存在单独的文件add-patch.c. 新代码仍然受到add.interactive.useBuiltin配置设置的保护,目前只能通过git add -p.

\n

实际功能遵循5cde71d64aff的原始实现(" git add --interactive", 2006-12-10, Git v1.5.0-rc0 -- merge),但不是太接近(例如,我们使用字符串偏移量而不是复制字符串,然后查看kj命令是否适用,在 C 版本中,我们记住哪个上一个/下一个块尚未确定,并使用它而不是当用户要求跳转时再次查看)。

\n

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

\n

虽然很容易使用这种转换git add -p作为工作的借口apply_all_patches(),以便它不想stdin文件中读取文件,而是接受,比如说,一个strbuf,但我们在这个阶段将避免使用这个特定的兔子洞。

\n
\n

Git 2.29(2020 年第四季度)中发现了重写工作的结论:“ add -i/ -p”机制已用 C 编写,但默认情况下尚未使用。
\n参与实验者默认feature.experimental

\n

请参阅Junio C Hamano ( )的提交 2df2d81(2020 年 9 月 8 日)。\n (由Junio C Hamano 合并 -- --提交 e96b271中,2020 年 9 月 18 日)gitster
gitster

\n
\n

add -ifeature.experimental:设置时使用内置版本

\n

确认人:约翰内斯·辛德林

\n
\n
\n

自 2.25 起,我们就已经并行实现了“ add -i/ -p”,并从 2.26 天起就一直在各种代码路径中使用它们,但从未将内置版本设为默认版本。

\n

我们已经发现并修复了内置版本中的一些极端情况错误,现在可能是开始将用户群从脚本版本切换到内置版本的好时机。

\n

让我们为那些选择加入的人启用内置版本feature.experimental让我们为那些选择加入豚鼠计划的

\n
\n

而且,在 Git 2.29(2020 年第 4 季度)中,仍然有一个“ add -i/-p ”:

\n

请参阅Jeff King的提交 1c6ffb5提交 dc62641(2020 年 9 月 7 日。\n (由Junio C Hamano 合并 -- --提交 694e517中,2020 年 9 月 18 日)peff
gitster

\n
\n

add-patch:修复反向返回码repo_read_index()

\n

签署人:Jeff King
\n签署人:Johannes Schindelin

\n
\n
\n

将块应用到带有“”的文件后add -p,Cpatch_update_file()函数会尝试刷新索引(就像 Perl 版本所做的那样)。
\n只有能够读入索引,我们才能刷新索引,因此我们首先检查 的返回值repo_read_index()
\n但与许多函数不同,其中“0”表示成功,该函数被记录为返回索引中的条目数。
\n因此我们应该用非负返回值来检查是否成功。

\n

测试和任何用户似乎都没有注意到这一点,可能是由于以下原因的组合:

\n
    \n
  • 这仅影响 C 版本,该版本还不是默认值
  • \n
  • 跟随任何瓷器命令,如“ git diff男人或“git commit ”,都会自动刷新索引。
  • \n
\n

但是您可以通过在“”阶段所有帅哥之后立即运行管道“ git diff-files( man )来看到问题add -p。\n运行新测试GIT_TEST_ADD_I_USE_BUILTIN=1。\n在没有匹配代码更改的情况下运行新测试会失败。

\n
\n
\n

在 Git 2.37(Q3 2022)中,前段时间用 C 重写了“ git add -iman) ,并且已经在测试中;重新实现现在默认向公众公开

\n

请参阅Johannes Schindelin ( )的提交 0527ccb提交 ed922dc(2021 年 11 月 30 日)。\n (由Junio C Hamano 合并 -- --提交 1fc1879中,2022 年 5 月 30 日)dscho
gitster

\n
\n

add -i:默认为内置实现

\n

签署人:约翰内斯·辛德林

\n
\n
\n

9a5315e中(“合并分支 \'js/patch-mode-in-others-in-c\'”,2020-02-05,Git v2.26.0-rc0 -合并在批次 #3中列出),Git 获取了( man )交互模式的内置实现,可以通过配置选项打开。git addadd.interactive.useBuiltin

\n

支持此旋钮的第一个官方 Git 版本是 v2.26.0。

\n

2df2d81 (“add -i: use thebuilt-in version when feature.experimental is set”, 2020-09-08, Git v2.29.0-rc0 -- mergelisted in batch #15 )中,这个内置实现是也可通过 启用feature.experimental
\n进行此更改的第一个版本是 v2.29.0。

\n

一年多(并且很少有错误报告)之后,是时候宣布内置实现成熟并默认打开它了。

\n

我们特意将add.interactive.useBuiltin配置保留在适当的位置,以便在意外情况下,如果用户在该实现中遇到以前未检测到的错误,则为他们提供“逃生舱口”。

\n
\n

git config现在包含在其手册页中:

\n
\n

设置为false可回退到交互式版本的原始 Perl 实现,git add而不是内置版本。
\ntrue默认的

\n
\n
\n

在 Git 2.40(2023 年第 1 季度)中,最终淘汰了脚本化的“ git add(