Git版本回退

Git版本回退


  • 作用:版本切换
  • 命令形式:git reset --hard commitID
    • commitID 可以使用git-loggit log指令查看
  • 如何查看已经删除的记录?
    • git reflog
    • 这个指令可以看到已经删除的提交记录

Git 版本回退(版本恢复)是指将代码库恢复到之前的某个状态。这在开发过程中非常常见,可能由于提交错误、引入了Bug或者需要撤销某些更改。Git 提供了多种方法来实现版本回退,主要包括 git resetgit revertgit checkoutgit reflog。下面详细介绍这些方法及其适用场景。

Git的版本回退操作默认是针对本地仓库的。当我使用 git reset 或其他回退命令时,它们最初只会影响我本地的代码库和提交历史。

1. *使用 git reset 回退版本


git reset 命令用于重置当前分支的指针到指定的提交,同时可以选择性地修改暂存区和工作目录。git reset 有三种模式:

1.1 git reset --soft <commit>软退回

将当前分支的指针(HEAD)移动到指定提交,相当于将本地仓库的状态退回到该提交点,但不会丢失任何工作进度。暂存区和工作目录中的更改都会保留,我可以基于这些更改进行进一步的修改或直接重新提交。

  • 适用场景:需要修改最近的提交,但保留更改以便重新提交。

  • 示例

    1
    git reset --soft HEAD~1

1.2 git reset --mixed <commit>混合回退

将当前分支的指针(HEAD)移动到指定的提交点,相当于将本地仓库的状态退回到该提交点。同时,重置暂存区,使其与指定提交的状态保持一致。工作目录中的更改则会保留,但它们不再处于暂存状态。这意味着可以基于这些保留的更改进行进一步的修改,或选择性地重新暂存并提交。

  • 适用场景:需要取消暂存的更改,但保留在工作目录中以便进一步修改。
  • 示例
    1
    git reset --mixed HEAD~1

1.3 git reset --hard <commit>硬退回

将当前分支的指针(HEAD)移动到指定的提交点,相当于将本地仓库的状态完全退回到该提交点。与 softmixed 模式不同,hard 模式会重置分支指针、暂存区,并且彻底重置工作目录。这意味着所有未提交的更改(包括暂存区和工作目录中的更改)都会被永久删除,使本地仓库的状态完全与指定提交一致。这种操作非常危险,因为所有未提交的工作都会丢失且无法恢复。

  • 适用场景:彻底回退到某个提交,丢弃所有未提交的更改。需谨慎使用。
  • 示例
    1
    git reset --hard HEAD~1

2. *使用 git revert 撤销提交


git revert 撤销提交是一个安全且常用的方法,它通过创建一个新的提交来撤销指定提交的更改,而不会修改提交历史。这对于已经推送到远程仓库的提交特别有效,因为它不会破坏历史记录。

2.1 如何使用 git revert 撤销提交

  1. 查看提交历史
    首先,需要确定要撤销的提交的哈希值(<commit>)。可以使用 git log 查看提交历史。

    1
    git log

    示例输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    commit abc1234 (HEAD -> main)
    Author: Your Name <you@example.com>
    Date: Thu Sep 21 14:00:00 2024 +0000

    Your commit message

    commit def5678
    Author: Your Name <you@example.com>
    Date: Wed Sep 20 14:00:00 2024 +0000

    Another commit message

    假设想撤销提交 abc1234

  2. **执行 git revert**:
    使用 git revert 命令来撤销指定的提交。需要提供要撤销的提交的哈希值。

    1
    git revert <commit>

    示例:

    1
    git revert abc1234

    解释
    这会创建一个新的提交,内容与 abc1234 相反,从而撤销 abc1234 中的所有更改。

  3. 解决可能的冲突
    如果撤销的提交与当前工作目录中的更改发生冲突,Git 会提示解决冲突。我们需要手动解决这些冲突,然后完成 revert 操作。

    • 解决冲突:编辑有冲突的文件,解决所有冲突。
    • 标记为已解决:使用 git add 将解决后的文件标记为已解决。
    1
    git add <conflicted-file>
    • 完成 revert:在解决所有冲突后,执行以下命令来完成 revert。
    1
    git revert --continue
  4. 提交更改
    如果没有冲突,Git 会自动为我们创建一个新的提交。我们可以使用默认的提交消息,或者编辑提交消息以说明撤销的原因。

    1
    git commit -m "Revert commit abc1234"
  5. 推送更改到远程仓库(如果需要):
    如果是在本地仓库中完成了撤销操作,并且希望将这些更改推送到远程仓库,可以使用以下命令。

    1
    git push origin <branch>

    解释
    将包含撤销更改的提交推送到远程仓库。

3. 使用 git checkout 切换到特定提交


git checkout 可以用于切换到某个特定的提交或分支。

  • 作用:查看或临时使用某个历史提交的状态。

  • 适用场景:需要查看旧版本代码或在旧版本基础上进行新的开发。

  • 示例

    1
    git checkout <commit>
  • 注意:在 detached HEAD 状态下进行更改不会影响任何分支,建议在此状态下创建新分支以保存更改。

    1
    git checkout -b new-branch <commit>

4. *使用 git reflog 找回丢失的提交


git reflog 记录了所有分支指针的移动历史,即使是通过 resetrebase 等操作导致的丢失提交也能通过 reflog 找回。

  • 作用:查看和恢复之前的分支状态,包括那些不在当前分支历史中的提交。

  • 适用场景:误用了 git reset --hard 丢失了重要的提交,需要找回这些提交。

  • 示例

    1
    2
    git reflog
    git reset --hard <reflog-commit>
  • 示例解释

    1
    2
    3
    4
    5
    6
    7
    git reflog
    # 输出类似:
    # abc1234 HEAD@{0}: reset: moving to HEAD~1
    # def5678 HEAD@{1}: commit: 添加新功能
    # ...

    git reset --hard def5678

    这将把分支指针重置回 def5678 提交,恢复之前的状态。

5. 使用 git stash 暂存未提交的更改


虽然不直接用于版本回退,git stash 可以临时保存未提交的更改,方便在回退或切换分支时保留工作进度。

  • 作用:暂时保存工作目录的更改,清理工作区以便进行其他操作。

  • 适用场景:需要切换分支或回退版本,但不想丢失当前未提交的更改。

  • 示例

    1
    2
    3
    git stash
    git reset --hard <commit>
    git stash pop

6. 总结


Git 提供了多种回退版本的方法,每种方法适用于不同的场景:

  • **git reset**:适用于本地开发,需要修改提交历史。需谨慎在共享分支上使用。
  • **git revert**:适用于公共分支,安全地撤销提交,不改变历史。
  • **git checkout**:用于查看旧版本或在旧版本上创建新分支。
  • **git reflog**:用于恢复丢失的提交,尤其在误操作后。
  • **git stash**:用于临时保存未提交的更改,辅助回退和切换分支。