日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Git 错误提交后该如何回滚操作

發布時間:2023/11/28 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Git 错误提交后该如何回滚操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. Git 架構

  • Workspace:工作區(當前用戶操作修改的區域)
  • Index / Stage:暫存區 (add 后的區域)
  • Repository:倉庫區或本地倉庫(commit 后的區域)
  • Remote:遠程倉庫(push 后的區域)

整體過程可以簡述為:

  • 工作區–>add–>暫存區–>commit–>本地倉庫區–>push–>遠程倉庫區
  • 遠程倉庫區–>fetch–>使用 refs\remotes 下對應分支文件記錄遠程分支末端 commit_id 和 本地倉庫區 -->merge–>工作區
  • 遠程倉庫區–>pull–>使用 refs\remotes 下對應分支文件記錄遠程分支末端 commit_id and 本地倉庫區 and 工作區

具體的 git 的組成部分和概念命令,請移步下述兩個博客(超鏈接):
Git 技術干貨!工作中 Git 的使用實踐和常用命令合集!
Git - 使用 git 不知道內部實現機制怎么行

新建一個 Git 倉庫,在 Git 倉庫中可邏輯上劃分三個區域——工作目錄、暫存區、版本庫,這三個區域是抽象的,Git 倉庫中以文件來記錄各個區域的內容。

Git 會追蹤工作目錄里文件及內容的變更。當我們在 Git 倉庫的工作目錄下新建三個文件,Git 會將新建的文件視作變更(圖中五角星表示被 Git 檢測到更改)。

我們想將 html 文件提交到倉庫中,首先將變更(新建的 HTML )從工作目錄添加到暫存區。然后將這個文件從暫存區提交到版本庫。這時才算拍攝了一組快照,提交的更改不會丟失。

當我們在工作目錄下修改了一個文件, Git 倉庫會識別文件修改部分(標記 2 顆星),然后我們將文件修改添加到暫存區,最后將文件修改提交到版本庫。

修改 CSS 文件,將修改添加到暫存區,再提交到倉庫。

問題:如果我們在工作目錄下第一次修改一個文件,并將它添加到暫存區,然后我們第二次修改文件,第二次修改沒有添加到暫存區,最后我們將文件 commit 到版本庫,請問倉庫的文件內容是第幾次修改的?請思考。

如果第一次修改 CSS 文件,添加到暫存區,再第二次修改 CSS 文件,現在執行 commit,提交到版本庫只有第一次修改的內容。


當執行 commit 時,只有暫存區中的內容會被提交到版本庫。

如果我們想要將第二次修改也 commit 到版本庫,我們必須先將第二次修改先添加到暫存區,第一次修改的暫存與第二次修改的暫存合并,然后執行 commit,倉庫中就會有第一次和第二次修改的內容。


添加到暫存區的內容會合并,一起提交到倉庫。

第一次修改 CSS 文件,添加到暫存區,但沒有提交倉庫;第二次修改 CSS 文件,添加到暫存區,會與第一次的修改合并,這時提交到版本庫的內容是兩次修改的合并。

2. 實踐

假設項目存在這么一個提交記錄:

$ git log
commit commit_id4 (HEAD -> master)
Author: test
Date:   Thu Aug 20 16:28:45 2020 +0800第三次修改 README 文件
commit commit_id3 (HEAD -> master)
Author: test
Date:   Thu Aug 20 16:28:45 2020 +0800第二次修改 README 文件
commit commit_id2
Author: test
Date:   Thu Aug 20 16:28:19 2020 +0800第一次修改 README 文件
commit commit_id1
Author: test
Date:   Thu Aug 20 16:26:59 2020 +080初始化項目

提交順序為:commit_id1 --> commit_id2 --> commit_id3 --> commit_id4
注意:在 git 中每次的 commit 都有一個 commit id 唯一標識當前的提交!

下面,我們先來解決小明的這個問題,使用git reset即可完美解決~

3. 問題解決

洋仔:小明,你的這個就可以用git reset 這個命令來完美的搞定,下面我們看一下如何解決

1、獲取當前提交的 commit id
命令:git log
獲取到當前項目分支下的所有 commit 記錄;
假設上述小明提交錯誤的 commit id 為commit id:commit_id4這一次提交;
他的上一次提交就是commit id:commit_id3 ,我們要將修改回滾到commit_id3的時刻!

小明:我想要把我剛才 commit 的修改保留下來,我修改的代碼不能給我刪除掉呀!
洋仔:沒問題

2、將某個 commit id 前的 commit 清除,并保留修改的代碼
命令:git reset <commit_id> 當前場景下就是:git reset commit_id3
將指定 commit_id 后的所有提交,都去除,并保留修改的代碼在本地的區域,也就是Workspace

小明:啊哈,這樣的話我就可以把錯誤代碼修改后再提交了; 但是我已經 push 到線上倉庫的數據怎么辦呢?
洋仔:別急,有辦法~

3、修改代碼完成后,將修改好的代碼 add 到暫存區,并提交到本地倉庫中
命令:git add <file_name> and git commit
當前場景下:git add . and git commit 將最新修改后的代碼 commit 則提交后的提交記錄假設如下:

可以看到,我們錯誤提交的commit_id4提交記錄消失,取而代之的是我們更新代碼后提交的記錄commit_id5; 這樣就完成了本地的代碼修改和更新

$ git log
commit commit_id5 (HEAD -> master)
Author: test
Date:   Thu Aug 20 16:28:45 2020 +0800第三次修改 README 文件-更新錯誤后提交
commit commit_id3 (HEAD -> master)
Author: test
Date:   Thu Aug 20 16:28:45 2020 +0800第二次修改 README 文件
commit commit_id2
Author: test
Date:   Thu Aug 20 16:28:19 2020 +0800第一次修改 README 文件
commit commit_id1
Author: test
Date:   Thu Aug 20 16:26:59 2020 +080初始化項目

整體流程如下:

git log
git reset commit_id3
修改代碼
git add .
git commit -m '第三次修改 README 文件-更新錯誤后提交'

洋仔:好了,小明,你的問題完美解決了
小明:哦吼,但是我還有一個問題: 如果我想要不保留回滾 commit 的修改,直接刪除掉修改!該怎么處理呢?
洋仔:簡單~ 我們整體看一下 git reset 命令

3.1 后悔藥 git reset

在進行下面的講解是,還是先假設有這么一個提交鏈:
commit_id1 --> commit_id2 --> commit_id3 --> commit_id4

git reset <param> commit_id2

reset 是將 HEAD 重新定位到commit_id2上,對于 commit_id3commit_id4 和本地當前的修改,對于不同的參數 param,會有不同的處理:

reset 命令有三種處理模式:

  • –soft:保留 commit 修改,將修改存儲到 index 中;也就是說 git add 后的區域
  • –mixed:保留 commit 修改,將修改存儲到本地工作區域中;也就是說 git add 前的區域
  • –hard:刪除 commit 修改,慎用!
  1. git reset --soft
    回滾 commit_id 前的所有提交,不刪除修改:
    git reset --soft commit_id
    重設 head,不動 index,所以效果是 commit_id 之后的 commit 修改全部在 index 中 將 id3 和 id4 的修改放到 index 區(暫存區),也就是 add 后文件存放的區域,本地當前的修改保留

    git reset --soft SHA 會將對應的 commit 更改回退到暫存區:

  2. git reset --mixed
    回滾 commit_id 前的所有提交,不刪除修改:git reset commit_id 等同于 git reset --mixed commit_id 與下述的 git reset --hard commit_id 效果不同。
    重設 head 和 index,不重設 work tree,效果就是 commit_id 之前的修改,全部在 work tree 中,為還未 add 的狀態 將 id3 和 id4 的所有修改放到本地工作區中,本地當前的修改保留。

    git reset --mixed SHA 會將對應的 commit 更改回退到工作目錄:

  3. git reset --hard
    回滾 commit_id 前的所有提交,將修改全部刪除:git reset --hard commit_id
    重設 head、index、work tree,也就是說將當前項目的狀態恢復到 commit_id 的狀態,其余的全部刪除(包含 commit_id 后的提交和本地還未提交的修改) 慎用!!

    git reset --hard SHA 會將對應的 commit 直接刪除,無法恢復。

    git reset --hard commit_id 該命令主要是用于代碼回退,僅對已經 commit 到本地的代碼有效。通過 git reflog 命令查看之前版本 id 信息。

    wohu@ubuntu-dev:~/git_demo/test_demo$ git reflog
    eda37f0 HEAD@{0}: commit: third commit
    8d2efe6 HEAD@{1}: commit: second commit
    14b5e12 HEAD@{2}: commit (initial): first commit
    wohu@ubuntu-dev:~/git_demo/test_demo$ cat README.md 
    - first commit
    - second commit
    - third commit
    wohu@ubuntu-dev:~/git_demo/test_demo$ 
    

    想再次切回到注釋為 second commit 版本下,可以再次通過 git reset --hard 8d2efe6 進行版本切換。

    wohu@ubuntu-dev:~/git_demo/test_demo$ git reset --hard 8d2efe6
    HEAD is now at 8d2efe6 second commit
    wohu@ubuntu-dev:~/git_demo/test_demo$ ls
    README.md
    wohu@ubuntu-dev:~/git_demo/test_demo$ cat README.md 
    - first commit
    - second commitwohu@ubuntu-dev:~/git_demo/test_demo$ 
    

3.2 后悔藥 git revert

小明:原來 git reset 這么強大呀! 但是我這還有個問題:

如果想要只操作修改中間的一個 commit,不對其他的 commit 產生影響; 也就是類似于我們只修改 commit_id2,而對 commit_id3 和 commit_id4 無影響,該怎么處理呢?

洋仔:(這么多問題,幸虧我懂,要不這次就丟大了。。) 簡單! git revert 命令!

適用場景: 在項目開發中,突然發現在前幾次的提交中,有一次提交中包含一個 bug; 當然我們可以進行一個新的修改,然后再提交一次; 但是,不優雅哈哈; 我們可以直接重做有 bug 的 commit~

為什么不直接去再添加一個 commit 呢?
git revert 是用于“反做”某一個版本,以達到撤銷該版本的修改的目的。
比如,我們 commit 了三個版本(版本一、版本二、 版本三),突然發現版本二不行(如:有 bug),想要撤銷版本二,但又不想影響撤銷版本三的提交,就可以用 git revert 命令來反做版本二,生成新的版本四,這個版本四里會保留版本三的東西,但撤銷了版本二的東西;

在 revert 命令中常用的就兩個:

  • git revert -e <commit_id>:重做指定 commit 的提交信息
  • git revert -n <commit_id>:重做執行 commit 的代碼修改
  1. git revert -e
    重做 commit_id 的提交信息,生成為一個新的 new_commit_id
    git revert -e commit_id

  2. git revert -n
    重做 commit_id 的提交git revert -n commit_id將 commit_id 中修改,放到 index 區,我們可以對他重新做修改并重新提交

git revert <commitHash>  回退指定提交記錄git revert --no-commit <commitHash> 
回退指定提交記錄 --no-commit 不會自動提交成一條 `commit` 后續手動操作git revert --no-commit <commitHash1> <commitHash2>  
回退多個提交記錄git revert --no-commit <commitHash1>..<commitHashN>
回退一定范圍的提交記錄,前開后閉(不包含 1,包含 N)

3.3 revert vs reset

  • git revert 是用一次新的 commit 來回滾之前的 commit,此次提交之前的 commit 都會被保留不動;
  • git reset 是回到某次提交,提交及之前的 commit 都會被保留,但是此 commit id 之后的修改都會被刪除或放回工作區等待下一次提交;

小明:還有這種操作,可以直接單獨操作提交過程中的某一個 commit! 太棒了!

4. 后悔藥git checkout

小明:還有最后一個問題:
如果我在一次開發中,發現某個文件修改錯誤了,想要將文件恢復到剛 pull 代碼時的狀態怎么辦呢?
洋仔:簡單! 看 git checkout 解決這個問題!

我們知道使用git checkout可以

  • git checkout <branch_name>切換分支

  • git checkout -b <branch_bame>創建分支等操作

它還有回滾指定文件的修改的功能,命令:git checkout -- <file_name>
上述語句的作用,就是將 file_name 的本地工作區的修改全部撤銷,有兩種情況:

  • 如果 file_name 在 commit 后沒有 add 過這個文件,則撤銷到版本庫中的狀態

  • 如果 file_name 在 commit 后 add 過這個文件,則撤銷到暫存區的狀態,也就是 add 后的狀態

總之,就是讓指定的文件回滾到最近的一次git add 或者 git commit時的狀態!

git checkout --file 該命令是對未提交到緩存區的代碼進行撤銷。創建空文件 Readme.md。通過 git status 查看文件在工作區的狀態。

wohu@ubuntu-dev:~/git_demo/test_demo$ echo "hello world" >> Readme.md 
wohu@ubuntu-dev:~/git_demo/test_demo$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
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:   Readme.mdno changes added to commit (use "git add" and/or "git commit -a")
wohu@ubuntu-dev:~/git_demo/test_demo$ 

然后執行 git checkout -- Readme.md。我們又回復到了修改前的版本。

wohu@ubuntu-dev:~/git_demo/test_demo$ cat Readme.md 
hello world
wohu@ubuntu-dev:~/git_demo/test_demo$ git checkout -- Readme.md
wohu@ubuntu-dev:~/git_demo/test_demo$ cat Readme.md 
wohu@ubuntu-dev:~/git_demo/test_demo$ 

我們再次對 Readme 內容進行編輯,并將其放入到緩存區中。

wohu@ubuntu-dev:~/git_demo/test_demo$ echo "hello world" >> Readme.md 
wohu@ubuntu-dev:~/git_demo/test_demo$ git add Readme.md 
wohu@ubuntu-dev:~/git_demo/test_demo$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:(use "git reset HEAD <file>..." to unstage)modified:   Readme.mdwohu@ubuntu-dev:~/git_demo/test_demo$ git checkout -- Readme.md
wohu@ubuntu-dev:~/git_demo/test_demo$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:(use "git reset HEAD <file>..." to unstage)modified:   Readme.mdwohu@ubuntu-dev:~/git_demo/test_demo$ 

此時執行 git checkout 沒有啥效果,如果想恢復就要用到我們接下來介紹的命令。

git reset HEAD -- file 該命令是將放入暫存區的代碼進行撤銷,放入到工作區中。

wohu@ubuntu-dev:~/git_demo/test_demo$ git reset HEAD -- Readme.md
Unstaged changes after reset:
M	Readme.md
wohu@ubuntu-dev:~/git_demo/test_demo$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
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:   Readme.mdno changes added to commit (use "git add" and/or "git commit -a")
wohu@ubuntu-dev:~/git_demo/test_demo$ 

這樣我們的 Readme.md 代碼又再次回到了工作區。再次進行 git checkout 將代碼內容進行恢復。

參考:
https://gitbook.cn/books/5f4db870237b0e7d7f238fa0/index.html
https://gitbook.cn/books/5ebca21b9b907c12334b6287/index.html

總結

以上是生活随笔為你收集整理的Git 错误提交后该如何回滚操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。