Git 在每一步更新工作目录时拆分最后提交和修改中间提交
我想将最近的提交C拆分为多个提交C(#=1,2,…等)。然而,每个中间提交C#都不能直接使用C中相应的部分更改来完成,但它们必须在某种程度上进行修改以“有意义”。此外,要确定提交C#“有意义”,工作目录需要处于表示此提交的状态,以便在提交前可以进行相应的更改,而不会丢失最终提交C的内容 就我而言,我有以下几点:Git 在每一步更新工作目录时拆分最后提交和修改中间提交,git,Git,我想将最近的提交C拆分为多个提交C(#=1,2,…等)。然而,每个中间提交C#都不能直接使用C中相应的部分更改来完成,但它们必须在某种程度上进行修改以“有意义”。此外,要确定提交C#“有意义”,工作目录需要处于表示此提交的状态,以便在提交前可以进行相应的更改,而不会丢失最终提交C的内容 就我而言,我有以下几点: 我提交了一些代码,其中包含太多要拆分的更改,因为 该程序在提交后被窃听,但不是在提交前,并且有太多的新特性使调试变得容易 我不能简单地删除一些特性而不破坏其他特性,因此我必须在对每个特
- 我提交了一些代码,其中包含太多要拆分的更改,因为
- 该程序在提交后被窃听,但不是在提交前,并且有太多的新特性使调试变得容易
- 我不能简单地删除一些特性而不破坏其他特性,因此我必须在对每个特性进行“部分提交”之前对其进行编辑
- 为了确保提交有意义,我检查程序是否仅使用这一新功能进行编译
- (显然)我不想丢失所有其他特性的代码,这样我就可以轻松地回到原来的commit C
所以我的问题是
- 如何拆分最新的提交并创建多个新的提交(仅包含部分更改)
- 如何在新提交之间编辑文件(在工作目录中),而不丢失组成原始提交的更改
- 可能有很多解决方案,我试图找到一个“简单”的解决方案。特别是不应该有丑陋的临时提交,不需要解决冲突,也不需要总是从提交C的状态开始编辑文件。我将把提交B称为C之前的那个
为此,我使用
git diff
创建补丁文件,并根据需要使用git apply
应用它们。详细内容:
- 首先,放弃最后一次提交并将更改保留在工作目录中
git reset HEAD~
- 为方便起见,请忽略修补程序文件
echo "*.diff" >> .gitignore
- 现在,在编辑文件之前,请创建一个修补程序,以便我们可以从C返回到版本。需要先将B中不存在的文件添加到索引中(否则修补程序将为空!),如下所示:
git add -N file #not needed for files that exist in B
- 创建补丁并将工作目录版本设置为B中的版本
git diff file >> file.diff git checkout file
- 对从B更改为C的每个文件重复这些步骤。现在将部分更改应用于索引和工作目录。首先,对于B中不存在的文件,我们必须再次删除它们(或者之前不签出文件)
- 然后进行部分更改并相应更新修补程序:
git apply file.diff rm file.diff git add -i #interactively stage only partial changes git diff file >> file.diff git checkout file
通过以上步骤,我可以进行部分更改,同时在工作目录中始终具有与部分提交相对应的版本(而不是C版本!)。相反,C版本“保存”在补丁中。通过一些额外的步骤,我可以编辑中间提交文件的版本
- 编辑
,然后再次创建修补程序,但以后必须反向应用这些修补程序。命名这些修补程序,例如,每次编辑的修补程序数量都会增加文件
git diff file >> file.reverse<#>.diff git add file
git-diff-file>>file.reverse.diff git添加文件
- 每次编辑都可以重复这些步骤,每次都创建一个额外的reverse.diff
- 在N编辑后,可以通过按正确顺序应用修补程序来创建将此最新版本恢复为C版本的修补程序
git apply -R file.reverse<N>.diff git apply -R file.reverse<N-1>.diff #... git apply -R file.reverse1.diff git apply file.diff rm file*.diff git diff file >> file.diff git checkout file
git apply-R file.reverse.diff git apply-R file.reverse.diff #... git apply-R file.reverse1.diff git apply file.diff rm文件*.diff git diff file>>file.diff git签出文件
file.diff
返回到C版本
注意:我创建问题+答案是因为我的git不流利,我相信我下次一定会忘记我是如何做到这一点的。。我发现了一些类似的答案,但没有解决我的确切问题,所以可能其他人会觉得这很有用。我肯定会使用
git reset--soft
来处理这种情况。比如说,你有你的分支,它叫featA。您需要在featA和featA~1之间创建一些中间修订。这就是我要做的:
git checkout -b temp featA # create branch temp from featA, check it out
git reset soft --HEAD~1 # put all changes between featA and feat~1 in index, ready to be commited.
# at this time you go to your files and edit them the way you want them to be on the first "new" revision. Revert changes at will, featA won't move no matter what
# when you are done, add everything to index
git commit -m "First new revision"
# now, for every new revision you want to create:
git checkout --detach featA
git reset --soft temp
# same thing.... set the files you want it for the following revision
# add to index
git commit "a new revision"
git branch -f temp # move temp pointer
# then in the _last_ revision, when you want this new revision to resemble featA
git checkout featA
git reset --soft temp
git commit -m "Final new revision"
或者,从配方的第二部分(第二次中间修订版和更高版本)开始,可以通过与tempA进行比较来处理,这样您就可以一点一点地进行更改,而不是针对每个新修订版返回完整的featA(如您在问题中所说,调整代码以使其有意义)
git checkout -b temp featA # create branch temp from featA, check it out
git reset soft --HEAD~1 # put all changes between featA and feat~1 in index, ready to be commited.
# at this time you go to your files and edit them the way you want them to be on the first "new" revision. Revert changes at will, featA won't move no matter what
# when you are done, add everything to index
git commit -m "First new revision"
# now, for every new revision you want to create:
git checkout --detach featA
git reset --soft temp
# same thing.... set the files you want it for the following revision
# add to index
git commit "a new revision"
git branch -f temp # move temp pointer
# then in the _last_ revision, when you want this new revision to resemble featA
git checkout featA
git reset --soft temp
git commit -m "Final new revision"