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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Git笔记(二)——[diff, reset]

發布時間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Git笔记(二)——[diff, reset] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

書接上回,直入主題!如果你是接著上篇來的,那么先運行git reset HEAD test.txt和git checkout test.txt來放棄當前的更改,使最新的commit回到“commit temp”,這個時候運行git status,會看到“nothing to commit, working directory clean”。這里,“nothing to commit”說明暫存目錄是空的,“working directory clean”說明你的工作目錄也沒有任何修改。

回到這種狀態是為了方便我們下面的講解,此時的SourceTree狀態為:

diff - 來,叔叔給你檢查身體

好好的一個diff命令能讓我想到的就是這句猥瑣的經典臺詞了,diff可以讓你比較項目中任意兩個狀態的差別。說到比較,自然就又有source和target了,那么diff命令最直觀的用法其實就是git diff source target。這里的source和target與checkout中的類似,可以是“commit的hash”,“分支名”,“快捷方式”。比如,我們想比較圖13中前兩個commit,運行git diff ce81811 6382c7d即可,得到的結果如下圖:

可以看到,比較的結果其實是以target為基準的,也就是說target相比于source有了哪些變化,圖15的結果中commit “6382c7d”比“ce81811”少了三行,多了一行,分別用減號和加號來表示。同樣,使用git diff master branch2和git diff HEAD branch2得到的結果與上面是一致的,分支名和“HEAD”一類的都可以看做是commit的快捷方式。

這種source和target都給的情況是最容易理解的,復雜就復雜在如果我們省略一個參數會怎么樣呢?比如運行git diff branch2結果如下圖所示:

可以看到,圖16的結果與圖15是相反的。也就是說git diff branch2與git diff branch2 HEAD的結果是一樣的,即如果只給一個參數,則這個參數為source,target默認為當前所在分支的最新的commit。現在就下這個結論對嗎?注意我們現在處在“暫存目錄為空”+“工作目錄clean”的狀況下,現在我們把工作目錄搞成dirty試試,給test.txt再加一行“test 6”并保存。這時再試試git diff branch2,結果如圖17所示:

可以看到新建的“test 6”也進去了。可以斷定,在工作目錄不clean的情況下,target默認表示的是工作目錄。這個結論是否還是為時尚早呢,如果暫存目錄有東西會怎么樣?運行git add test.txt,然后繼續git diff branch2,發現結果與圖17是一致的,這還是不能說明問題,因為此時工作目錄與暫存目錄是一致的(都到test 6)。那么我們再加一行“test 7”,這時工作目錄為“test 7”,暫存目錄還是“test 6”,此時運行git diff branch2,發現“test 7”這一行也被加了進去。這個時候我們基本可以斷定,target默認顯示的確實是工作目錄。

前面看了省略一個參數的情況,那倆參數都省略會咋樣呢?運行git diff結果如下圖:

可以看到比較結果為只增加了“test 7”,所以這個時候的source是暫存目錄,而target還是工作目錄。為了驗證這個推測,我們運行git add test.txt,將“test 7”的修改也add到暫存目錄,這時運行git diff,返回結果為空,因為此時暫存目錄和工作目錄是一致。我們做一次提交git commit -m "commit 6,7",這時,暫存目錄為空,工作目錄clean,繼續運行git diff,還是空的。到這里我們可以斷定,如果兩個參數都省略,那么默認source為暫存目錄,默認target為工作目錄。

前面的情況涉及到“各個commit之間的比較”,“各個commit與工作目錄的比較”,“暫存目錄與工作目錄的比較”,那么只差一種情況了,我想比較“暫存目錄”和“各個commit”怎么整呢?為了實現這個,我們先給暫存目錄來點東西:加一行“test 8”并保存,然后git add test.txt,然后在編輯test.txt加一行“test 9”,這么做的原因是讓暫存區有東西而且暫存區與工作目錄不同。這時運行git diff --cached branch2,可以發現結果為下圖:

從圖中可以發現“test 8”在而“test 9”不在,說明此時的target已經變成暫存區了。

總結一下diff的各種情況:

  • git diff source target返回的結果是target相對于source的變化,這里的source和target可以是commit的hash/分支名/快捷方式
  • 如果只給一個參數,則這個參數就是source,而默認的target是工作目錄,如果工作目錄clean的話,則target為當前所在分支的最新commit
  • 如果一個參數都不給,默認的source是暫存目錄,而target還是工作目錄
  • 如果想要使暫存目錄作為target的話,需要使用--cached參數
  • 在繼續往下走之前,先將剛才的更改全部提交,運行git add test.txt和git commit -m "commit 8,9"。

    reset - 有了我你隨便咋折騰都行

    版本控制最大的好處就是可以方便的找到以前的版本并恢復,所以從這個角度來說reset命令的地位還是比較重要的,可以讓你無所顧忌的隨便蹂躪整個項目。說到恢復,也有source和target的概念,這里的source肯定就是各個commit(包含分支名和快捷方式),而target根據不同的參數可能是暫存目錄或工作目錄或兩者同時都是target。比如我們選定當前commit的父commit作為source,運行git reset HEAD~ test.txt,提示有Unstaged change,此時SourceTree里的Uncommitted changes的狀態如下圖:

    從圖20中可以發現,暫存區域的文件狀態與父commit時一致,而改變是減掉了“test 8”和“test 9”兩行,說明工作目錄并沒有發生變化(工作目錄含有這兩行)。可以看到這種情況下的target其實是暫存目錄,它并沒有改變工作目錄。說到這里,把前面欠的課補上,還記得前面我們做git add的反操作時用了git reset HEAD test.txt,其實也是將HEAD狀態的文件恢復到了暫存區,工作目錄保持不變,而那時最新commit的文件狀態和工作目錄是一致的,所以最終產生的效果就是“git add反操作”。其實這里的HEAD也可以省略,因為默認的source就是當前所在分支的最新commit。更進一步,文件名test.txt也可以省略,默認會將Repo里的所有文件恢復,因為此時我們就只有這一個文件,所以效果是一樣的。

    再介紹reset的其他參數之前,我們想把剛才的reset再給reset掉,很簡單,只要再運行一遍git reset即可,因為我們需要的其實是“git add的反操作”。然后加參數運行reset,git reset --soft HEAD~,注意這里我們并不是省略文件名,而是一旦加了--soft就不能跟文件路徑,而是恢復整個項目的所有文件了,結果如下圖所示:

    可以看到,這次reset直接改變了HEAD,原先的“commit 8,9”消失了,最新的commit變成了原先的HEAD~,但這次reset仍然沒有修改工作目錄,只是將“commit 8,9”的文件狀態add到了暫存區。既然有--soft參數,那肯定會有--hard參數,這次我們保持當前的狀態,直接運行git reset --hard ce81811(commit temp所對應的hash),發現當前最新的commit變成“commit temp”,并且暫存區域是空的,然后工作目錄也是clean的,說明--hard參數不管運行命令前處于什么狀態,都直接將工作目錄恢復到“commit temp”的狀態,清空暫存區域。這也比較符合--hard這個單詞強硬的意思。此時的SourceTree狀態圖為:

    從圖中可以看出,“commit temp”之前的commit都已經丟失了,整個項目被強制恢復到了“commit temp”所在的狀態。

    總結一下reset的用法:

  • git reset [commit hash/分支名/快捷方式] [文件名]類似“git add的反操作”,直接將所在commit的文件狀態恢復到暫存區域。省略commit則默認為HEAD,省略文件名默認為所有文件。只改變暫存目錄,不改變工作目錄,當前commit不變。
  • git reset --soft [commit hash/分支名/快捷方式]軟恢復,將恢復前所在commit的文件狀態恢復到暫存區,當前最新commit為參數中的commit。只改變暫存目錄,不改變工作目錄,當前commit改變。
  • git reset --hard [commit hash/分支名/快捷方式]硬恢復,強制將整個項目恢復為參數中的commit時的文件狀態,清空暫存目錄,工作目錄clean。暫存目錄和工作目錄同時被改變,當前commit改變。
  • 關于reset命令的其他補充:當前HEAD已經位于“commit temp”,是不是前面的commit都找不回來了?當然不會,reset過的操作也是可以被reset的。有兩種方法:

    • 如果記得“commit 8,9”的hash(從圖20中可以看到),則直接git reset --hard 1a222c3,則項目直接強制恢復到“commit 8,9”所在的狀態。
    • 如果不記得的話,運行git reflog,這個命令會輸出一個列表,包含HEAD發生的所有變化。如下圖:

    在圖23中可以發現“commit 8,9”所對應的條目為1a222c3 HEAD@{9}: commit: commit 8,9,第一項就是commit hash,第二項自然是快捷方式了。那么只要我們運行git reset --hard HEAD@{9}即可。注意,我的reflog輸出結果可能與你的不同,因為寫教程的需要我可能做了很多額外的操作。

    P.S. 顯然兩篇也不夠啊,發現主要是Retina屏的截圖太尼瑪大了。。。下篇再講剩下的吧!


    from:?http://pinkyjie.com/2014/08/09/git-notes-part-2/

    總結

    以上是生活随笔為你收集整理的Git笔记(二)——[diff, reset]的全部內容,希望文章能夠幫你解決所遇到的問題。

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