撤消并恢复git的提交
1. 简介
在使用 Git 时,我们经常发现自己需要撤消或恢复提交,无论是回滚到特定时间点还是恢复特别麻烦的提交。在本教程中,我们将介绍在 Git 中撤消和恢复提交的最常用命令。我们还将演示这些命令的运行方式有何细微差别。
2. 使用git checkout查看旧提交
首先,我们可以使用git checkout命令查看项目在特定提交时的状态。我们可以使用git log命令查看 Git 存储库的历史记录。每个提交都有一个唯一的 SHA-1 标识哈希,我们可以将其与 git checkout一起使用 ,以便重新访问时间轴中的任何提交。
在此示例中,我们将重新访问具有识别哈希e0390cd8d75dc0f1115ca9f350ac1a27fddba67d的提交:
git checkout e0390cd8d75dc0f1115ca9f350ac1a27fddba67d
我们的工作目录现在将匹配我们指定提交的确切状态。因此,我们**能够查看项目的历史状态并编辑文件,而不必担心丢失当前项目状态。**我们在这里所做的一切都不会保存到存储库中。这称为分离的 HEAD状态。
我们可以对本地修改的文件使用 git checkout将它们恢复到它们的工作副本版本。
3. 使用git revert恢复提交
我们使用git revert命令恢复 Git 中的提交。请务必记住,此命令不是传统的撤消操作。相反,它反转提交引入的更改并生成具有反向内容的新提交。
这意味着**只有在我们想要应用特定提交的逆时才应该使用git revert。**它不会通过删除所有后续提交来恢复到项目的先前状态——它会撤消单个提交。
git revert不会将引用指针移动到我们正在恢复的提交,这与其他“撤消”命令(例如git checkout和git reset )形成对比。相反,这些命令将HEAD ref 指针移动到指定的提交。
让我们看一个恢复提交的例子:
mkdir git_revert_example
cd git_revert_example/
git init .
touch test_file
echo "Test content" >> test_file
git add test_file
git commit -m "Adding content to test file"
echo "More test content" >> test_file
git add test_file
git commit -m "Adding more test content"
git log
git revert e0390cd8d75dc0f1115ca9f350ac1a27fddba67d
cat test_file
在此示例中,我们创建了一个 test_file,添加了一些内容并提交了它。然后,我们在运行git log之前向文件添加并提交了更多内容, 以识别我们想要恢复的提交的提交哈希。
在这种情况下,我们正在恢复最近的提交。最后,我们运行了git revert并通过输出文件的内容验证了提交中的更改是否已恢复。
4. 使用git reset恢复到以前的项目状态
使用git reset 命令可以在使用 Git 的项目中恢复到以前的状态。此工具撤消更复杂的更改。它具有与 Git内部状态管理系统相关的三种主要调用形式:–hard、–soft和*–mixed*。了解使用哪个调用是执行git revert最复杂的部分。
git reset在行为上与git checkout相似。但是,git reset将移动HEAD ref 指针,而git checkout对HEAD ref 指针进行操作并且不移动它。
为了理解不同的调用,我们将看看 Git 的内部状态管理系统——也称为 Git 的三棵树。
第一棵树是工作目录。此树与本地文件系统同步,表示对文件和目录中的内容进行的即时更改。
接下来,我们有暂存索引树。该树跟踪工作目录中的更改——换句话说,使用git add选择的更改 将存储在下一次提交中。
最后一棵树是提交历史。git commit命令将更改添加到存储在提交历史中的永久快照。
4.1. -hard
使用此调用的最危险和最常用的选项是提交历史记录引用指针,以更新到指定的提交。在此之后,暂存索引和工作索引重置以匹配指定提交的索引。对暂存索引和工作目录的任何先前挂起的更改都会重置以匹配提交树的状态。我们将丢失staging index和working index中的任何待处理或未提交的工作。
继上面的示例之后,让我们向文件提交更多内容,并向存储库提交一个全新的文件:
echo "Text to be committed" >> test_file
git add test_file
touch new_test_file
git add new_test_file
git commit -m "More text added to test_file, added new_test_file"
假设我们然后决定恢复到存储库中的第一个提交。我们将通过运行以下命令来实现:
git reset --hard 9d6bedfd771f73373348f8337cf60915372d7954
Git 会告诉我们HEAD 现在位于指定的提交哈希处。查看test_file的内容表明我们最新的文本添加不存在,并且我们的new_test_file不再存在。这种数据丢失是不可逆转的,因此我们了解*–hard*如何与 Git 的三棵树一起工作至关重要。
4.2. -soft
当使用*–soft*进行调用时,引用指针会更新,并且重置会停在那里。因此,暂存索引和工作目录保持相同状态。
在我们之前的示例中,如果我们使用–soft 参数,我们提交给暂存索引的更改不会被删除**。我们仍然能够在staging index中提交我们的更改。
4.3. –mixed
默认操作模式,如果没有传递参数,–mixed提供了*–soft和–hard*调用之间的中间立场。暂存索引重置为指定提交的状态,并且引用指针更新。暂存索引中任何未完成的更改都将移至工作目录。
在上面的示例中使用*–mixed意味着我们对文件的本地更改不会被删除。然而,与–soft*不同的是,这些更改已从暂存索引中撤消并等待进一步的操作**。