我遇到了一个问题,我认为最好的解决方案是捕获项目的当前状态并将其应用于新分支中的新提交。
以下是我的git工作流程的概述:
以下是导致这种情况的时间顺序:
我相信这是因为在local / feature1中的提交历史记录现在包含一个合并提交,其中包括.pem文件更改。在实现挂钩之前,此文件已添加到Origin / master,因此不受挂钩限制。但是,合并提交到我的分支将随我的代码更改一起提交,因此它会被钩标记。
这时,我想从local / feature1的提交历史记录中删除.pem文件,而无需实际删除这些文件。由于.pem文件已经存在,因此在此时重新提交和重新压缩提交不会解决问题。删除.pem文件无济于事,因为它们实际上需要存在于项目中(无关的故事)。将我的分支恢复为未合并状态也不是一种选择,因为这样上传的原点/功能与原点/主文件太过时了,因此无法进行审核。
显而易见的解决方案似乎是:
# Copy current state of the project to a backup directory
cp -r . ../backup
rm -rf ../backup/.git
# Reset project to latest official state
git checkout local/master
git pull
# Regenerate local branch so the merged changes aren't included as local commits
git branch -D local/feature1
git checkout -b local/feature2
# Copy the desired project state back in and commit it
cp -rf ../backup/. .
git add --all
git commit -m "Regenerating feature branch"
rm -rf ../backup
# Upload without being restricted by hook
git push --set-upstream origin feature2
我觉得应该有一种使用git原生进行此操作的方法,而不必直接弄乱文件系统。这样做有魔术吗?也许通过git stash
?
答案 0 :(得分:3)
这里不需要git stash
。 git stash
已经保存了完整的快照,但是所有提交也是如此。没有提交是差异。 Git通过将提交与另一个完整的快照进行比较,将提交转换为差异:两个快照中的差异就是差异。许多命令(包括git stash
)通过将提交与其父对象进行比较来完成很多工作。例如,git cherry-pick
将要选择的提交与其父提交进行比较,以查看发生了什么更改,然后将这些更改应用于您现在所在的任何位置(也进行第二次比较并使用合并引擎)。 / p>
git commit
从 index 的内容而不是工作树中的内容制作快照。因此,如果您希望某个现有分支上的某个新提交与任何现有提交完全匹配,那么您要做的就是删除索引中的所有内容,并将其替换为其他某个提交中的所有内容。 (随即出现了工作树,因此您可以看到发生了什么。)有一种显而易见的简单方法:
$ git checkout br1
$ git rm -r . # from the top level: remove everything
$ git checkout br2 -- . # extract everything from commit at tip of br2
$ git commit
这将进行新的提交,将其添加到br1
的尖端,其内容来自br2
。 (没有未跟踪的文件会顺风顺水,因为根据定义,未跟踪的文件不在索引中,但是请注意在提取的提交中跟踪的文件在旧的br1
技巧中未跟踪,反之亦然。)< / p>
有一个简短的版本:
$ git read-tree -m -u br2
$ git commit
会减少工作树的搅动(有时对于make
来说很重要):read-tree将提交读入索引,而-u
使Git更新工作-树匹配。由于此处git read-tree
仅具有一个参数,因此它将抛出当前索引内容,并删除其中(以及工作树中)不在br2
提交中的任何文件。与较长的变体一样,这不会影响未跟踪的文件。
答案 1 :(得分:2)
我不理解为何仅在本地/主控上重新建立本地/功能1(在步骤6)是不够的。它将从上游引入pem更改,并在其上重播提交,因此当您推送时,pem的内容将不会被触及。
如果您先前已将--force推到origin / feature1,则必须推--force,但是通常应使用推力功能部件。