所以,你知道你需要在你的git repo中做一些清理工作,可能会使用rebase或其他东西,如果你做错了,可能会让你很难撤消。
有没有办法告诉Git“保存整个本地git仓库的这种状态,以便我可以回滚所有这一点,万一出现问题?”类似于“沙盒模式”的东西,它可以让你安全地玩你的回购,执行潜在的灾难性操作,而不会有任何混乱的风险。
我不是在谈论在历史记录中的特定点添加标记或其他内容,而是在某些内容中重置所有分支上的git repo所做的更改。回滚所有东西的可能性(所有git历史/状态)。与OSX Time Machine类似的东西。
更新2019-02-19:我应该澄清,通过“潜在的灾难性操作”,我并不是指代码本身,而是实际上在使用git中的repo结构,使用例如git reset --hard
或类似的命令。
您可以在其他地方使用Git存储库复制您的文件夹,并在那里做任何您想做的事情(假设只有本地操作)。这不会影响您原来的本地仓库,如果您想放弃副本中的更改 - 只需删除它并再次复制即可。
Git存储库本身就是一个沙箱。
克隆您的存储库并在克隆的repo中播放。你可以做任何事情,你甚至可以完全摧毁它(删除它)。只要你没有git push
,原件保持不变。
如果您想重新开始,只需删除克隆并再次重新创建它。或运行:
git checkout master
git reset --hard origin/master
checkout
命令使master
成为本地仓库的当前分支。 reset
命令将本地当前分支和工作树恢复到master
远程上的分支origin
的状态(假设您开始在master
分支上玩)。
Git非常努力地不丢失或损坏数据,并且已经提供了帮助您恢复工作的工具。它的basic build blocks是持久不可变的数据结构。
例如,不是直接重新定位分支foo
,而是创建一个名为foo/rebase
的新分支,其中foo
当前是,检查出来并改为使用foo/rebase
。您将看到,将不会修改从foo
可以访问的任何提交,因此您可以安全地使用新分支。就像一个事务,你可以回滚工作(只需删除foo/rebase
)或提交该操作(使用foo
使foo/rebase
指向reset --hard
,或者可能合并)。
在任何情况下,您仍然拥有reflog,它保留对任何分支或标记当前不可访问的对象的引用。您也可以克隆您的存储库,但在大多数情况下这有点过分。在你的情况下,你似乎要大规模改变分支,所以我必须承认克隆存储库可能是最好的方法。
tl; dr:可以做到,这是git的标准行为;
我知道这个问题已经解决了,但我确实感到有必要澄清这种情况,以便提供关于git如何工作的更高层次的直觉。
@Magne正在寻找的是git默认是如何工作的:
你做出的每一个提交都是你的安全点,你所做的一切都不会让它消失(......除了少数例外......)
只要可以通过浏览提交树,从现有分支和标记的尖端开始,然后从父提交移回父提交,Git就会保留您提交的所有提交。
如果您处于提交A,并且将其重新绑定到另一个分支上,那么您的新提交A'(它与A不同,因为它具有不同的父项)将是您的HEAD移动到的位置,这意味着您将保留当你继续提交时,那个工作。
提交A会发生什么?它还在那里! (仅限时间,供应持续)。只是没有分支或标签可以再到达它。但是如果你还记得提交哈希,你仍然可以查看它。如果您不记得哈希值,git reflog
将向您显示您访问过的所有提交,因此该哈希值将在该历史记录中正确显示,并且您将能够至少从提交消息中识别它。
因为旧的提交A无法从任何分支或标签访问,所以一旦确定重新压缩其内部存储,git将在一段可配置的时间后最终摆脱它。
只要你标记你的承诺,就不会被删除。所以...随意改变,如果你在重新定位后有任何疑问,请回到git reflog
并标记旧的commit A
,以便你可以随时回到它。
如果你决定你毕竟不喜欢那个rebase,那么你将git checkout
那个旧的提交,你用力(git branch -f <branch-name> <commit-that-will-be-tip-of-branch>
)将你的分支的尖端移动到它,然后检查那个分支(git checkout <branch-name>
)。
如果没有一个好的图表,这有点难以理解。我绝对鼓励读者去玩这个“git模拟器”:http://onlywei.github.io/explain-git-with-d3/它真的有助于可视化正在发生的事情。