一、为什么要学习Git?
Git是一个分布式版本控制工具,那么,什么是分布式?什么又是版本控制呢?
分布式版本控制工具意味着每个开发者的本地计算机都有一个完整的版本库副本,包括代码的完整历史记录,而不像集中式版本控制系统那样,版本库只存在于中央服务器。
以一个写小说的团队为例。在集中式系统中,就好像有一个专门的文件柜(中央服务器)来存放小说稿件。每次作者(开发者)想要修改、查看版本,都要到这个文件柜去操作。而Git这种分布式系统,就像是每个作者自己都有一个一模一样的文件柜(本地仓库),里面有完整的小说从最初构思到现在所有的版本记录。作者可以在自己的文件柜里自由创作、修改、回溯版本,不用每次都依赖一个公共的文件柜。
二、Git的好处及例子
- 离线工作方便:假设你是一个程序员,在火车上或者没有网络的偏远山区,你仍然可以在本地仓库里继续写代码、修改代码、查看代码历史版本等。因为你的本地仓库是完整的,等你有网络的时候,再把本地修改推送到远程仓库(比如团队共用的代码库)。
- 协作灵活:一个软件开发团队中,多个程序员可以同时开发不同的功能。例如,程序员A开发用户登录功能,程序员B开发用户注册功能。他们都可以在自己的本地仓库独立地开发、测试,当功能完成后,再将自己的修改合并到远程仓库的主分支或者其他分支上。这样可以减少相互干扰,提高开发效率。
- 版本回溯安全:如果在开发过程中,发现新的代码版本出现了严重的错误。使用Git可以很容易地回退到之前稳定的版本。就好像写小说过程中,发现新的章节写得很混乱,那可以轻松地回到之前逻辑清晰的章节版本,而且所有的历史版本在本地仓库都有记录,随时可以查看当时的代码状态或者小说内容。
- 使用
git reset
命令回退提交- 原理:
git reset
命令主要用于重置当前分支的 HEAD 指针。HEAD 指针指向当前分支上的最新提交,通过移动这个指针,可以改变仓库的状态。它有三种模式:--soft
、--mixed
(默认模式)和--hard
,这三种模式在回退时对工作区、暂存区和版本库的影响有所不同。
- 具体操作步骤和影响:
- --soft 模式:
- 假设你已经提交了一个新的版本(提交哈希为
abc123
),现在想要回退这个提交,但是希望保留这个提交中的修改内容在暂存区。可以使用命令git reset --soft HEAD~1
(HEAD~1
表示回退一个提交)。 - 这种模式下,版本库中的提交会被回退,但是工作区和暂存区不受影响。也就是说,被回退的提交中的所有修改会被放在暂存区,就好像你刚刚执行了
git add
操作把这些修改添加到暂存区一样,你可以重新调整暂存区的内容后再次提交。
- 假设你已经提交了一个新的版本(提交哈希为
- --mixed 模式(默认):
- 同样假设已经提交了一个新的版本(提交哈希为
abc123
),使用命令git reset HEAD~1
(这里省略了--mixed
,因为它是默认模式)来回退这个提交。 - 这种模式下,版本库中的提交会被回退,暂存区也会被清空,但是工作区会保留修改内容。这意味着被回退的提交中的修改会被放回工作区,就好像你刚刚编辑完文件还没有执行
git add
操作一样。你可以重新选择哪些修改要添加到暂存区,然后再提交。
- 同样假设已经提交了一个新的版本(提交哈希为
- --hard 模式:
- 假设你想要彻底删除最后一个提交(提交哈希为
abc123
)并且不保留任何修改,使用命令git reset --hard HEAD~1
。 - 这种模式下,版本库中的提交会被回退,暂存区会被清空,工作区也会被强制恢复到回退后的状态。也就是说,被回退的提交中的所有修改都会被删除,无论是在版本库、暂存区还是工作区,这个操作是不可逆的,所以使用时要非常谨慎。
- 假设你想要彻底删除最后一个提交(提交哈希为
- --soft 模式:
- 原理:
- 使用
git revert
命令回退提交- 原理:
- 与
git reset
不同,git revert
命令是通过创建一个新的提交来撤销(或部分撤销)之前的提交。它不会修改历史提交记录,而是在历史记录中添加一个新的提交,这个新提交的内容是对要回退的提交的反向修改。
- 与
- 具体操作步骤:
- 假设你想要回退一个提交(提交哈希为
abc123
),在命令行中执行git revert abc123
。 - Git 会自动打开一个文本编辑器,让你编辑提交信息(通常默认的提交信息会显示它是在回退哪个提交)。你可以根据需要修改这个信息,然后保存并关闭编辑器。
- Git 会创建一个新的提交,这个提交的内容会抵消被回退提交的修改。例如,如果被回退的提交是添加了一行文本,那么
git revert
创建的新提交就会删除这行文本。这样,历史记录中仍然保留了原来的提交,但是通过新的提交将其影响进行了反向操作。
- 假设你想要回退一个提交(提交哈希为
- 原理:
- 理解
git reset --hard
的作用git reset --hard
是一个比较强力的 Git 命令。它会将你的工作目录、暂存区和 HEAD 指针都重置到指定的提交。这意味着所有在这个提交之后的修改(包括已经添加到暂存区和未添加到暂存区的修改)都会被丢弃。- 例如,你有一个仓库,提交历史是 A - B - C,当前在 C 这个提交上,执行
git reset --hard B
,那么工作目录和暂存区的内容会变成 B 提交时的状态,C 提交之后的所有更改都丢失了。
- 如果刚刚执行了
git reset --hard
并且想恢复之前的状态- 查看 Git 日志
- 首先,你可以通过
git reflog
命令来查看 Git 的引用日志。这个日志记录了 HEAD 和分支引用的更新情况,包括你使用git reset --hard
操作之前的提交信息。 - 例如,在命令行中输入
git reflog
,会得到类似如下的输出:收起
plaintext
3a4b5c6 (HEAD -> master) HEAD@{0}: reset: moving to 3a4b5c6 7d8e9f0 HEAD@{1}: commit: Added new feature
- 这里
HEAD@{0}
表示最近的操作,HEAD@{1}
表示再往前一次的操作等。从这个日志中可以找到在git reset --hard
之前的提交哈希值(如上面例子中的7d8e9f0
)。
- 首先,你可以通过
- 恢复到之前的提交
- 一旦找到了想要恢复的提交哈希值,就可以使用
git reset --hard <commit - hash>
命令来恢复到那个提交的状态。 - 例如,如果想要恢复到上面日志中的
7d8e9f0
这个提交,就可以在命令行中输入git reset --hard 7d8e9f0
。
- 一旦找到了想要恢复的提交哈希值,就可以使用
- 查看 Git 日志
- 如果无法通过
git reflog
恢复(比如reflog
的记录也被清除了)- 本地备份恢复(如果有)
- 如果你有本地的备份(如文件的副本或者之前导出的项目版本),可以将备份文件复制到项目目录中,覆盖当前的文件。不过这种方法比较麻烦,而且可能会丢失在备份之后所做的一些正确的修改。
- 远程仓库恢复(如果适用)
- 如果你的代码已经推送到远程仓库,并且远程仓库没有被同步进行
git reset --hard
操作,你可以通过git fetch
(从远程仓库获取最新的提交记录)和git reset --hard origin/<branch - name>
(将本地分支重置为远程分支的状态)来恢复。 - 例如,如果你的分支是
master
,可以先执行git fetch
,然后执行git reset --hard origin/master
。不过这种方法会丢失本地在git reset --hard
之后但没有推送到远程仓库的正确修改。
- 如果你的代码已经推送到远程仓库,并且远程仓库没有被同步进行
- 本地备份恢复(如果有)
如何查看Git的提交历史记录?
在回退提交后,如何恢复工作区的内容?
除了git reset,还有其他方式回退提交吗?