Git中有许多撤销的可能性
介绍
在本教程中,我们将向您展示在Git中撤消工作的不同方法,我们假设您具有基本的工作知识。检查GitLab的Git文档供参考。此外,我们将只提供命令的一些一般信息,这足以让您开始使用简单的案例/示例,但要了解更高级的内容,请参阅Git的书.
我们将根据当前开发中的更改阶段解释一些不同的技术来撤消更改。另外,记住这一点Git中没有任何内容被真正删除。这意味着在Git自动清除分离的提交(不能通过分支或标记访问)之前,可以使用git reflog
命令,并直接使用commit-id访问它们。阅读更多关于重做撤销在下面的部分中。
本指南是根据发展阶段您希望从何处撤销更改,以及是否与其他开发人员共享更改。由于Git正在跟踪更改,因此创建或编辑的文件处于未分级状态(如果创建了,则Git不会跟踪它)。将其添加到存储库(git添加
你把一个文件放进上演了状态,然后提交(git提交
)到本地存储库。之后,文件可以与其他开发人员共享(git推
).以下是我们将在本教程中介绍的内容:
分支策略
Git是一个去中心化的版本控制系统,这意味着除了整个存储库的常规版本控制之外,它还可以与其他存储库交换更改。为了避免混乱真相的多重来源,必须遵循各种开发工作流,这取决于您的内部工作流如何撤消或更改某些更改或提交。GitLab流在开发相同功能和无缝协作时,为开发人员之间的冲突提供了良好的平衡,但默认情况下,它不支持多个开发人员联合开发相同功能。当多个开发人员在同一个分支上开发相同的特性时,每次同步的冲突是不可避免的,但是一个适当的或选择的Git工作流将防止在特性完成时丢失或不同步。你也可以阅读这篇博客文章Git提示和技巧学会如何轻松做Git中的东西。
撤销本地更改
在将更改推送到任何远程存储库之前,它们只会影响您自己。这拓宽了你如何处理撤销它们的选择。尽管如此,当地的变化可能处于不同的阶段,每个阶段都有不同的应对方法。
未分级的本地更改(在提交之前)
当进行了更改,但没有将其添加到分阶段树中时,Git本身会提出一个解决方案,以丢弃对某些文件的更改。
假设你编辑了一个文件,要用你最喜欢的编辑器修改内容:
vim <文件>
既然你没有Git add
对于暂存,它应该在未暂存的文件下(或者如果创建了文件则不跟踪)。您可以通过以下方式确认:
$git状态在分支主机上你们的分公司是最新的“起源/主”.未分级的更改为提交:(使用"git add …" 更新将要提交的内容)(使用"git checkout——…" 放弃改变在工作目录)修改:<文件>没有添加任何更改以提交(使用“git添加”和/或"git commit -a")
此时,有3个选项可以撤销本地更改:
丢弃所有的局部更改,但保留它们以备可能的重用晚些时候
git藏
丢弃对文件的本地更改(永久地)
git checkout--<文件>
永久放弃对所有文件的所有本地更改
git重置——努力
在执行之前Git重置——硬
,请记住,还有一种方法可以临时存储更改,而无需使用git藏
.该命令将重置对所有文件的更改,但也会保存这些更改,以备以后需要应用这些更改时使用。你可以在下面的部分.
快速保存本地更改
你正在开发一个功能,这时老板带着一项紧急任务过来了。由于您的特性不完整,但您需要交换到另一个分支,您可以使用git藏
为了保存您所做的工作,交换到另一个分支,提交,推送,测试,然后返回到上一个特性分支,执行Git stash pop
继续你离开的地方。
上面的示例表明,放弃所有更改并不总是首选选项,但是Git提供了一种方法来保存它们以供以后使用,同时将存储库重置为没有更改的状态。这是通过Git的存储命令实现的git藏
,这实际上会保存您当前的工作并运行Git重置——硬
,但它也有各种额外的选项,如:
Git库保存
,它支持包括临时提交消息,这将帮助您识别更改,以及其他选项Git收藏列表
,它列出了所有以前没有存储的提交(是的,可以有更多)流行
艾德Git stash pop
,它重新执行以前存储的更改并将其从存储列表中删除Git stash应用
,它重新执行以前存储的更改,但将它们保留在存储列表中
阶段性的本地更改(在提交之前)
假设您已经向登台树添加了一些文件,但是您想从当前提交中删除它们,但又想保留这些更改—只需将它们移出登台树即可。您还可以选择放弃使用的所有更改Git重置——硬
或者想想git藏
如前所述。
让我们从使用您最喜欢的编辑器编辑一个文件开始,以更改内容并将其添加到暂存
vim <文件>Git add
文件现在被添加到暂存中,由git状态
命令:
$git状态在分支主机上你们的分公司是最新的“起源/主”.要提交的更改:(使用"git reset HEAD …" 对unstage)新建文件:
现在你有4个选项来撤销你的更改:
将文件还原到当前提交(HEAD)
git reset HEAD
卸载所有内容—保留更改
git重置
丢弃所有局部更改,但将其保存为晚些时候
git藏
永远抛弃一切
git重置——努力
已提交的本地更改
一旦提交,版本控制系统就会记录您的更改。因为您还没有将更改推送到远程存储库,所以您的更改仍然不是公开的(或与其他开发人员共享)。在这一点上,撤销事情要容易得多,我们有相当多的变通方案。一旦你推送了你的代码,你将有更少的选择来解决你的工作。
不修改历史记录
在整个开发过程中,一些先前提交的更改不再适合最终解决方案,或者是bug的来源。一旦您找到了触发bug的提交,或者一旦您有了错误的提交,您就可以使用Git revert commit-id
.该命令反转(交换)提交中的添加和删除,因此它不会修改历史记录。保留历史有助于将来注意到过去尝试过的一些更改没有成功。
在我们的示例中,我们将假设存在提交一个
,B
,C
,D
,E
按此顺序承诺:A-B-C-D-E
,B
是要撤消的提交。有许多不同的方法来标识提交B
同样糟糕的是,其中之一是传递一个范围git平分
命令。提供的范围包括最近一次已知的正确提交(我们假设一个
)和第一个已知的错误提交(在这里检测到错误——我们假设E
).
得到等分A…E
对分将为我们提供中间提交测试的commit-id,然后指导我们完成简单的对分过程。你可以读到更多在Git官方工具中在我们的示例中,我们将以commit结束B
,这引入了bug/错误。关于如何从存储库中删除它(或它的一部分),我们有4个选项。
- 撤销(交换添加和删除)提交引入的更改
B
.
git revert commit-B-id
- 从提交中撤销对单个文件或目录的更改
B
,但要保持它们处于分阶段状态
git checkout commit-B-id
- 从提交中撤销对单个文件或目录的更改
B
,但要保持它们处于未上演状态
git reset commit-B-id
还有一条命令我们也不能忘记:创建一个新分支从更改不适用或开发进入死胡同的地方开始。例如,您已经完成了提交
a b c d
在你的特征分支上,然后你想C
和D
是错误的。此时,您可以重置为B
一定要承诺F
(这将导致push的问题,如果被强制push,其他开发者也会有问题),因为分支现在看起来A-B-F
,这与其他开发人员在本地拥有的内容相冲突改变历史),或者直接签出提交B
创建一个新的分支并提交F
.在最后一种情况下,其他人仍然可以做他们的工作,而你有新的方法来把它做好,并在以后把它合并回来。或者,使用GitLab,您可以择优挑选提交到一个新的合并请求。git checkout commit-B-idgit checkout- bnew-path-of-feature# Create
git提交——一个
修改历史记录
有一个用于修改历史记录的命令是git变基
.命令提供交互模式(-我
标志),使您可以:
- 重述提交消息(也有
Git commit—修改
用于编辑上次提交消息) - 编辑提交内容(由提交引入的更改)和消息
- 南瓜多个提交合并为一个提交,并具有自定义或聚合的提交消息
- 下降提交——简单地删除它们
- 更多的选择
让我们来看几个例子。还有提交a b c d
要在哪里删除提交B
.
- 将当前提交D的范围重新设置为A:
git变基-我一个
- 命令打开您编写的最喜欢的编辑器
下降
在提交前B
,但你离开默认选择
与所有其他提交一起。保存并退出编辑器以执行重基。记住:如果您想取消,请在保存并退出编辑器之前删除整个文件内容
如果您想修改提交中引入的内容B
.
将当前提交D的范围重新设置为A:
git变基-我一个
命令打开您最喜欢的文本编辑器
编辑
在提交前B
,但保留默认值选择
与所有其他提交一起。保存并退出编辑器以执行重基现在进行编辑并提交更改:
git提交——一个
你可以在中找到更多的例子下面的小节将解释如何修改历史记录
重做撤销
有时你意识到你撤销的更改是有用的,你想要恢复它们。因为第一段,你很幸运。命令git reflog
使你能够回忆通过引用或应用commit-id分离本地提交。尽管如此,不要期望在reflog中看到真正的旧提交,因为Git会定期清除提交遥不可及的通过分支或标签.
要查看存储库历史并跟踪旧的提交,可以使用下面的命令:
$Git refflog show#输出示例:b673187 HEAD@{4}: merge 6e43d5987921bde189640cc1e37661f7f75c9c0b:合并“递归”策略。eb37e74 HEAD@{5}:变基-我(完成):返回裁判/首长/主人eb37e74 HEAD@{6}:变基-我(选择):提交C97436 c6 HEAD@{7}:变基-我(开始): checkout 97436c6eec6396c63856c19b6a96372705b08b1b…88年f1867 HEAD@{12}: commit: commit97436 c6 HEAD@{13}: checkout:从97436c6eec6396c63856c19b6a96372705b08b1b移动到测试97436 c6 HEAD@{14}: checkout:从master迁移到97436c605年cc326 HEAD@{15}: commit:提交6 e43d59 HEAD@{16}: commit: commit
命令输出显示存储库历史。在第一列中有commit-id,在第二列中,旁边有数字头
指示在操作指示符(commit, rebase, merge,…)之后进行了多少次提交,然后是该操作的结束描述。
在不更改历史记录的情况下撤消远程更改
该主题与修改提交的本地更改而不修改历史大致相同。它应该是撤销任何远程存储库或公共分支上的更改的首选方式。请记住,当您希望保留错误开发的历史,并从某个点重新开始时,分支是最好的解决方案。分支使您能够将现有的更改包含在新的开发中(通过合并),它还提供了清晰的时间表和开发结构。
如果您想要还原某些引入的更改提交id
您可以简单地恢复它提交id
(交换添加和删除)在新创建的提交:您可以使用
Git revert commit-id
或者创建一个新的分支:
Git checkout commit-idgit checkout- bnew-path-of-feature
通过修改历史撤消远程更改
这在你想要的时候很有用隐藏某些东西——比如密钥、密码、SSH密钥等。它是,也不应该用来隐藏错误,因为如果有其他错误,它会使调试变得更加困难。这样做的主要原因是您失去了真正的开发进度。还要记住,即使修改了历史记录,提交也只是分离的,仍然可以通过commit-id访问-至少在所有存储库执行分离提交的清理(自动发生)之前。
在哪些地方修改历史记录通常是可以接受的
修改的历史记录打破了其他开发人员的开发链,因为修改的历史记录没有匹配的提交id。因此,它不应用于任何公共分支机构或分支机构可能可供其他开发人员使用。当为大型开源存储库(例如。GitLab CE),是可以接受的南瓜提交到一个单独的文件中,以更好地展示您的贡献历史。请记住,这也会删除合并请求中附加到某些提交的注释,所以如果您需要在GitLab中保留可追溯性,那么修改历史记录是不可接受的。合并请求的特性分支是公共分支,可能由其他开发人员使用,但项目流程和规则可能允许或要求您使用git变基
(改变历史记录的命令),以减少审查完成后目标分支上显示的提交数量(例如GitLab)。有一个Git merge—squash
命令,它可以做到这一点(在合并时将功能分支上的提交压缩到目标分支上的单个提交)。
注意:的提交历史记录
主
或者共享分支
如何修改历史记录
在您知道要修改的内容(历史记录中的距离或旧提交的范围)之后,使用Git rebase -i commit-id
.该命令将显示从当前版本到所选commit-id的所有提交,并允许修改、压缩和删除这些提交。
$git变基-我commit1-id . . commit3-id选择 选择 选择 #重base commit1-id..commit3-id到(3个命令) ##命令:# p, pick =使用commit# r, reword =使用commit,但是编辑commit消息# e,编辑=使用提交,但停止修改# s, squash =使用commit,但合并到之前的commit中# f, fixup = like "squash",但是丢弃这个提交的日志信息# x, exec =使用shell运行命令(剩下的行)#删除提交#这些线可以重新排序;它们是从上到下执行的。#如果你删除了一行,COMMIT将会丢失。#然而,如果你删除了所有的东西,重置将被中止。#注意,空提交会被注释掉
注意:需要注意的是,输出中的注释清楚地指出,如果您决定终止,那么不要只是关闭编辑器(因为这实际上会修改历史记录),而是删除所有未注释的行并保存。
这是原因之一git变基
应该在共享和远程分支上谨慎使用。但是不要担心,在将其推回远程存储库之前不会有任何问题(因此您可以在本地自由地探索不同的结果)。
修改历史记录从commit-id到HEAD(当前提交)git变基-我提交id
从提交中删除敏感信息
Git还允许您从过去的提交中删除敏感信息,并且可以修改进度中的历史记录。这就是为什么我们把它包含在本节中,而不是作为一个独立的主题。要做到这一点,您应该运行git filter-branch
,它使您能够使用特定的过滤器.这个命令使用rebase来修改历史记录,如果你想从历史记录中删除某些文件,使用:
git filter-branch——tree-filter“rm文件名”头
自git filter-branch
命令在大型存储库中可能很慢,但是有一些工具可以使用Git的一些特性来加快常见任务的执行速度(这正是删除敏感信息文件的目的)。另一种选择是高炉煤气Repo-cleaner.请记住,这些工具更快,因为它们不提供与web工具相同的完整功能集git filter-branch
可以,但是要关注特定的用例。
结论
在任何版本控制系统中,都有各种各样的撤销工作的选项,但是由于Git的去中心化特性,这些选项会根据过程的阶段而增加(或限制)。Git还支持重写历史记录,但应该避免这样做,因为当多个开发人员对相同的代码库做出贡献时,可能会导致问题。