使用git checkout和git reset回退到歷史版本

Git是一個分佈式版本控制系統,它會保存文件修改的歷史版本,能夠使用下面的命令回退文件到某個歷史版本:git

  • git checkout <commit>:把整個git倉庫文件回退到 commit 參數指定的版本
  • git checkout [<commit>] [--] <filepath>:回退 filepath 文件爲 commit 參數指定的版本
  • git reset <commit>:把git的HEAD指針指向到 commit 對應的版本,本地文件內容不會被回退
  • git reset --hard <commit>:把git的HEAD指針指向到 commit 對應的版本,本地文件內容也會被回退

git checkout <commit>

git checkout <commit> 命令把整個git倉庫文件回退到 commit 參數指定的版本,該參數值能夠是具體的commit hash值,也能夠經過HEAD index來指定。例如,HEAD^ 對應最新版本的上一個版本,那麼 git checkout HEAD^ 命令回退git倉庫下的文件內容到上一個版本,同時從當前分支脫離,處在一個未命名分支下面:bash

$ git checkout HEAD^
Note: checking out 'HEAD^'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 8ba05ec...
$ git branch
* (detached from 8ba05ec)
  master
複製代碼

此時用 git log 命令查看log信息,最新的log已經變成前面 HEAD^ 指定的commit信息。
因爲脫離了原先的分支,修改本地文件,並執行 git commit 進行提交,不會影響原先分支。
即,若是想在原先分支上直接回退代碼,不能使用這個命令。分佈式

git checkout [<commit>] [--] <filepath>

git checkout [<commit>] [--] <filepath> 命令只回退 filepath 文件到 commit 參數指定的版本,不影響其餘文件,[--] 表示 -- 是可選參數,用於指定後面跟着的參數只是文件路徑,而不是branch分支名或者commit信息。ui

若是當前有一個branch分支名是 hello.c,且當前目錄下有一個 hello.c 文件,那麼不加 -- 參數時,git checkout hello.c 表示切換到 hello.c 分支,而不是覆蓋 hello.c 文件的改動。這種場景下,必須用 git checkout -- hello.c 指定覆蓋 hello.c 文件的改動,-- 參數能夠消除歧義。this

當前 git checkout [<commit>] [--] <filepath> 命令的行爲跟 git checkout [<commit>] 命令有所差別,具體說明以下:spa

  • git checkout [<commit>] 回退整個git倉庫的文件。而當前命令只回退指定文件
  • git checkout [<commit>] 會從原先分支脫離,並影響git log顯示的commit信息。而當前命令會停留在原先分支下,不影響git log顯示的commit信息
  • git checkout [<commit>] 切換以後,用git status查看,會提示"nothing to commit, working directory clean";而當前命令切換後,用git status查看,提示"Changes to be committed",指定回退的文件被添加到了git的staged區域,執行git commit,會多出一條新的commit信息

git reset <commit>

git reset <commit> 命令把git的HEAD指針指向到 commit 對應的版本,本地文件內容不會被回退,會停留在原先分支下。此時,用 git log 命令查看log信息,最新的log已經變成commit對應的信息。用 git status 命令查看,通常會提示有些文件被改動,即本地文件內容和git的staged區域內容不一致,相似於本地文件在當前git倉庫的版本上進行了一些修改:版本控制

$ git reset HEAD^
Unstaged changes after reset:
M       hello.c
$ git status
On branch new_branch_name
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   hello.c

no changes added to commit (use "git add" and/or "git commit -a")
複製代碼

在執行這個 git reset 命令以後,若是想讓本地文件也回退到指定的版本,能夠再使用 git checkout [--] <filepath> 命令來覆蓋本地文件內容。
執行 git reset 命令後不會從當前分支脫離,若是想在當前分支上,將本地代碼回退,就能夠使用這種方法。指針

git reset --hard <commit>

git reset --hard <commit> 命令把git的HEAD指針指向到 commit 對應的版本,本地文件內容也會被回退,不須要再執行 git checkout 命令來回退本地文件內容。code

因爲 git reset 會回退 git log 顯示的commit信息,使用 git log 命令看不到原先最新的commit hash值,沒法使用該commit hash值來恢復成原先最新的版本,能夠使用 git log -g 命令來看到全部操做過程的commit信息,就能看到原先最新的commit hash值,而後再次恢復。orm

相關文章
相關標籤/搜索