用簡單的英語,「git reset」有什麼做用?

我看到有趣的帖子解釋了關於git reset微妙之處。 git

不幸的是,我讀的越多,我就越不能徹底理解它。 我來自SVN背景,Git是一個全新的範例。 我很容易變得善變,但Git更具技術性。 安全

我認爲git reset接近hg revert ,但彷佛存在差別。 服務器

那麼git reset究竟作了什麼? 請包括如下詳細說明: svn

  • 選項--hard , - --soft--merge ;
  • HEAD使用的奇怪符號,如HEAD^HEAD~1 ;
  • 具體用例和工做流程;
  • 對工做副本, HEAD和您的全球壓力水平的影響。

#1樓

當您提交git的東西時,首先必須暫存(添加到索引)您的更改。 這意味着在git認爲它們是提交的一部分以前,你必須git添加你想要包含在這個提交中的全部文件。 讓咱們先來看看git repo的圖像: 在此輸入圖像描述工具

因此,如今很簡單。 咱們必須在工做目錄中工做,建立文件,目錄和全部。 這些更改是未跟蹤的更改。 要跟蹤它們,咱們須要使用git add命令將它們添加到git索引。 一旦將它們添加到git索引中。 若是咱們想將它推送到git存儲庫,咱們如今能夠提交這些更改。 學習

但忽然間咱們知道咱們提交了一個額外的文件,咱們在索引中添加了不須要推入git存儲庫。 這意味着咱們不但願索引中的該文件。 如今的問題是如何從git索引中刪除該文件,由於咱們使用git add將它們放在索引中,因此使用git rm是合乎邏輯的? 錯誤! git rm將簡單地刪除該文件並將刪除添加到索引中。 那麼如今該怎麼辦: ui

使用:- spa

git重置 線程

它清除您的索引,保持您的工做目錄不變。 (只是取消暫停一切)。 指針

它能夠與許多選項一塊兒使用。 使用git reset有三個主要選項: - hard, - soft和--mixed 。 重置時,這些會影響除HEAD指針以外的重置。

首先, - 重置一切。 您當前的目錄將徹底像您一直關注該分支同樣。 工做目錄和索引將更改成該提交。 這是我常用的版本。 git reset --hard就像svn revert

接下來,徹底相反的-soft ,不會重置工做樹和索引。 它只移動HEAD指針。 這使您的當前狀態的任何更改都與您在目錄中切換到的提交不一樣,而且「暫存」以進行提交。 若是您在本地進行提交但還沒有將提交推送到git服務器,則能夠重置爲先前的提交,並從新發送一個良好的提交消息。

最後, - mix複製索引,但不重置工做樹。 所以,全部更改仍然存在,可是「未分級」而且須要git add'ed或git commit -a 。 咱們有時會使用這個,若是咱們使用git commit -a承諾了更多,咱們可使用git reset -mixed返回提交,添加咱們想要提交的東西並提交它們。

git revert和git reset之間的區別 : -


在簡單的話,git的復位「修復未提交的錯誤」Git將還原爲命令,以「修復COMMITED錯誤」的命令。

這意味着若是咱們在某些更改中犯了一些錯誤並提交併將其推送到git repo,那麼git revert就是解決方案。 若是咱們在推送/提交以前已經識別出相同的錯誤,咱們可使用git reset來解決問題。

我但願它能夠幫助你擺脫困惑。


#2樓

通常來講, git reset的功能是獲取當前分支並將其重置爲指向其餘位置,並可能帶來索引和工做樹。 更具體地說,若是您的主分支(當前已檢出)是這樣的:

- A - B - C (HEAD, master)

而且你意識到你但願master指向B而不是C,你將使用git reset B將其移動到那裏:

- A - B (HEAD, master)      # - C is still here, but there's no branch pointing to it anymore

題外話:這與結帳不一樣。 若是你運行git checkout B ,你會獲得這個:

- A - B (HEAD) - C (master)

你最終處於一個獨立的HEAD狀態。 HEAD ,工做樹,索引所有匹配B ,但主分支在C處留下。 若是你在這一點上作了一個新的提交D ,你會獲得這個,這可能不是你想要的:

- A - B - C (master)
       \
        D (HEAD)

請記住,reset不會進行提交,它只是更新一個分支(指向提交的指針)以指向不一樣的提交。 其他的只是索引和工做樹會發生什麼的詳細信息。

用例

git reset在下一節中對各類選項的描述中介紹git reset許多主要用例。 它能夠真正用於各類各樣的事情; 常見的線程是全部這些都涉及重置分支,索引和/或工做樹以指向/匹配給定的提交。

要當心的事情

  • --hard可能會讓你真的失去工做。 它會修改您的工做樹。

  • git reset [options] commit會致使你(丟棄)提交。 在上面的玩具示例中,咱們丟失了提交C 它仍然在回購中,您能夠經過查看git reflog show HEADgit reflog show master找到它,但它實際上不能從任何分支訪問。

  • Git會在30天后永久刪除此類提交,但在此以前,您能夠經過再次指向分支來恢復C( git checkout C; git branch <new branch name> )。

參數

解釋手冊頁,最多見的用法是git reset [<commit>] [paths...] ,它會將給定路徑重置爲給定提交的狀態。 若是未提供路徑,則重置整個樹,若是未提供提交,則將其視爲HEAD(當前提交)。 這是git命令的常見模式(例如checkout,diff,log,雖然確切的語義各不相同),因此它不該該太使人驚訝。

例如, git reset other-branch path/to/foo全部內容重置爲其餘分支中的狀態, git reset -- . 將當前目錄重置爲HEAD中的狀態,而且簡單的git reset會將全部內容重置爲HEAD中的狀態。

主要工做樹和索引選項

有四個主要選項能夠控制在重置期間工做樹和索引起生的狀況。

請記住,索引是git的「臨時區域」 - 當你說準備提交git add時,事情就會發生。

  • --hard使一切都與你重置的提交相匹配。 這多是最容易理解的。 您全部的本地更改都會被破壞。 一個主要用途是吹走你的工做而不是切換提交: git reset --hard意味着git reset --hard HEAD ,即不要更改分支可是去除全部本地更改。 另外一種是簡單地將分支從一個地方移動到另外一個地方,並使索引/工做樹保持同步。 這能夠真正讓你失去工做,由於它會修改你的工做樹。 很是肯定你想在運行任何reset --hard以前扔掉當地的工做 - reset --hard

  • --mixed是默認值,即git reset意味着git reset --mixed 。 它重置索引,但不重置工做樹。 這意味着您的全部文件都是完整的,但原始提交與您重置的文件之間的任何差別都將顯示爲具備git status的本地修改(或未跟蹤文件)。 當你意識到你作了一些很差的提交時,使用它,但你想保留你已經完成的全部工做,這樣你就能夠修復它並從新發送。 爲了提交,你必須再次將文件添加到索引( git add ... )。

  • --soft不會觸及索引工做樹。 全部文件都與--mixed同樣完整,但全部更改都顯示爲changes to be committed使用git status changes to be committed (即在準備提交時簽入)。 當你意識到你作了一些很差的提交時使用它,可是工做都很好 - 你須要作的就是以不一樣的方式從新發送它。 索引是不變的,所以您能夠根據須要當即提交 - 結果提交將具備與重置以前相同的內容。

  • --merge最近被添加,旨在幫助您停止失敗的合併。 這是必要的,由於git merge實際上容許您嘗試與髒工做樹(具備本地修改的工做樹)合併,只要這些修改在不受合併影響的文件中。 git reset --merge重置索引(如--mixed - 全部更改都顯示爲本地修改),並重置受合併影響的文件,但--mixed其餘文件。 這將有望恢復在糟糕合併以前的一切。 你一般會將它用做git reset --merge (意思是git reset --merge HEAD ),由於你只想重置合併,而不是實際移動分支。 ( HEAD還沒有更新,由於合併失敗)

    更具體地說,假設您已經修改了文件A和B,而且嘗試在修改了文件C和D的分支中進行合併。因爲某種緣由合併失敗,而且您決定停止它。 你使用git reset --merge 。 它將C和D帶回到它們在HEAD ,但僅對A和B進行修改,由於它們不是嘗試合併的一部分。

想知道更多?

我確實認爲man git reset對此很是有用 - 也許你須要對git的工做方式有一點了解才能真正沉入其中。 特別是,若是您花時間仔細閱讀它們,那些詳細說明索引和工做樹中全部各類選項和案例的文件狀態的表很是有用。 (可是,它們很是密集 - 它們以很是簡潔的形式傳達了大量上述信息。)

奇怪的表示法

你提到的「奇怪的符號」( HEAD^HEAD~1 )只是指定提交的簡寫,而沒必要使用像3ebe3f6這樣的哈希名稱。 它徹底記錄在git-rev-parse手冊頁的「指定修訂版」部分 ,包含大量示例和相關語法。 插入符號和波形符號實際上意味着不一樣的東西

  • HEAD~HEAD~1縮寫,表示提交的第一個父級。 HEAD~2表示提交的第一個父親的第一個父親。 將HEAD~n想象爲「在HEAD以前提交n」或「HEAD的第n代祖先」。
  • HEAD^ (或HEAD^1 )也表示提交的第一個父級。 HEAD^2表示提交的第二個父級。 請記住,正常的合併提交有兩個父級 - 第一個父級是合併的提交,第二個父級是合併的提交。 通常來講,合併實際上能夠有任意多的父母(章魚合併)。
  • 所述^~運算符能夠串成,如在HEAD~3^2 ,第三代祖先的第二個親本HEADHEAD^^2 ,的第一個親本的第二個親本HEAD ,甚至HEAD^^^ ,至關於HEAD~3

插入符號和波浪形


#3樓

請記住,在git你有:

  • HEAD指針 ,它告訴您正在進行的提交
  • 工做樹 ,表示系統上文件的狀態
  • 暫存區域 (也稱爲索引 ),它「 分級 」更改,以便之後能夠一塊兒提交

請包括如下詳細說明:

--hard , - --soft--merge ;

隨着危險程度的增長:

  • --soft移動HEAD但不觸及暫存區域或工做樹。
  • --mixed移動HEAD並更新暫存區域,但不更新工做樹。
  • --merge移動HEAD ,重置暫存區域,並嘗試將工做樹中的全部更改移動到新的工做樹中。
  • --hard移動HEAD 並將你的臨時區域和工做樹調整到新HEAD ,扔掉全部東西。

具體用例和工做流程;

  • 若是你想轉移到另外一個提交併修補一些東西而不「失去你的位置」,請使用--soft 。 你須要這個不多見。

-

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

-

  • 當您想要查看另外一次提交時的內容時,請使用--mixed (這是默認設置),但您不但願丟失已有的任何更改。

  • 若是要移動到新位置,請使用--merge ,但將已有的更改合併到工做樹中。

  • 使用--hard擦除全部內容並在新提交中開始新的事件。


#4樓

請注意,這是一個簡化的解釋,旨在做爲了解這一複雜功能的第一步。

對於想要在每一個命令以後可視化項目狀態的視覺學習者可能會有所幫助:


對於那些使用打開顏色的終端的人(git config --global color.ui auto):

git reset --soft A你會看到B和C的東西是綠色的(上演並準備提交)

git reset --mixed A (或git reset A ),你會看到B和C的東西是紅色的(未分階段,準備上演(綠色),而後提交)

git reset --hard A你將不會再看到B和C的變化(就好像它們從未存在過)


或者對於那些使用像'Tower'或'SourceTree'這樣的GUI程序的人

git reset --soft A ,你會在'staged files'區域看到B和C的東西準備提交

git reset --mixed A (或git reset A ),你會在'unstaged files'區域看到B和C的東西,準備移動到staged而後提交

git reset --hard A你將不會再看到B和C的變化(就好像它們從未存在過)


#5樓

TL; DR

git reset Staging重置爲上次提交。 使用--hard還能夠將工做目錄中的文件重置爲上次提交。

更長的版本

但這顯然是簡單化的,所以許多至關冗長的答案。 在撤消更改的上下文中,我更有意義地閱讀git reset 。 例如看到這個:

若是git revert是一種撤消更改的「安全」方式,您能夠將git reset視爲危險方法。 使用git reset撤消(而且任何ref或reflog再也不引用提交)時,沒法檢索原始副本 - 它是永久撤消。 使用此工具時必須當心,由於它是惟一可能丟失工做的Git命令之一。

來自https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

還有這個

在提交級別,重置是一種將分支的提示移動到另外一個提交的方法。 這可用於從當前分支中刪除提交。

來自https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations

相關文章
相關標籤/搜索