情景:当发出拉取请求时,我希望接收者能够理解它所做的更改。我发现将它们压缩为一个提交可能会令人困惑,尤其是在以下情况下:
还有对代码的编辑也被移动-diff将其呈现为批量删除和添加,而不是突出显示编辑。
代码被添加到一系列类似的部分,例如case语句、级联ifs、yacc productions-diff通常将更改重新构造为重叠部分(例如,它不添加部分,而是使用上一部分的开头,添加新的结尾和另一个开头,然后使用上一部分的结尾);添加新代码结束,在某些情况下,挑出一些小的相似之处,然后删除并插入大量相同的代码。(我意识到diff使用lcs并且速度惊人——但有时它的结果很难理解,即使考虑到diff没有语法意识,也无法识别您看到的代码“部分”)。
顺便说一句:我使用git diff --color-words --ignore-space-change,这很好,但也是错误的重建,可以隐藏细节-我担心接受者可能会使用普通的git diff,看到完全不同的东西(他们可以重建不同)。
task:好的,显然解决这个问题的方法是将pull请求分成不同的提交。有时,这些可能是我开始的实际提交,所以我所需要做的只是一开始就不要重新定位/压缩。但我发现,即使这样,差异也可能不清楚(特别是出于上述原因(2)),我需要进一步分离它们。
最明显的方法是使用git add --patch/-p。但是,对于重叠的更改,修补程序很难使用-您可以ivide and even dit the hunks,但是当您想要的更改结合了添加、删除和公共代码时,考虑反转差异有点令人费解。
我实际做的是直接编辑文件:删除我不想要的部分并提交;然后撤消删除(用我的编辑器),并提交。使用实际的源代码比使用diff更清楚、更直观——但这感觉像是我在与git抗争,并且做得不对(而且,依赖编辑器撤销似乎是偶然的)。
我想到的是先git stash文件,通过删除我不想要的部分来准备第一次提交;然后git stash apply来“撤消”删除以准备第二次提交。但我不确定你是否能在一个rebase(还没试过)的过程中做到这一点。
问:我花了好几个小时才做完这件事…我想通过练习我会进步的,但是…
我走对了吗?有更好的办法吗?你能在一开始就防止错误重构的diff吗?我是不是太努力了?
(公平地说,这是前一段时间对微妙而复杂的代码所做的许多编辑,花这些时间揭示了更深层次的见解。)

最佳答案

基于these answers,在启动交互式rebase(get rebase -i ...)并编辑一个提交之后:

git reset HEAD^     # reverts index to previous commit (not change files)
                    # so it's as if you are just about to add and commit
git stash           # save
git stash apply     # get it back
...edit the file, deleting the changes you don't want in the first commit
git add .
git commit -m "...first changes..."

git stash apply     # get it back again (ie undo the above delete)
...(I needed to resolve a merge conflict)
git add .
git commit -m "...second changes..."

git rebase --continue

遗憾的是,没有一个e可以保存更改而不还原。可能有一个更平滑的方法来做这件事。
令我惊讶的是,你可以在一个交互式的回扣中使用git的全部功能。您可以忽略正在编辑的旧提交,而添加两个提交;您可以保存并应用。我可能需要研究git stash copy是如何实际实现的,并停止将其视为一个抽象。实际上,rebase手册页的标题是splitting commits

08-27 21:05
查看更多