交互式教程!帶你深入理解 Git 原理

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"綜述"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如下圖所示,有四個模塊。這個獨立的我們稱之爲 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":",其他靠在一起的三個我們稱之爲 "},{"type":"text","marks":[{"type":"italic"}],"text":"開發環境"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/24\/2464da0c7d496218ce816e2bb90970d6.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從獨立的這個模塊開始說,"},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" 是你推送你的改動並且希望與他人共享的地方,同樣你也可以從中獲取到他人的改動。如果你使用過其他的版本控制系統,那這個概念並沒有什麼新鮮的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"開發環境"},{"type":"text","text":" 是在你本地計算機上的。它的三個部分指的是你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 、"},{"type":"text","marks":[{"type":"italic"}],"text":"暫存區"},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 。在開始使用 Git 前,我們將先了解有關這些概念的知識。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"請選擇一個要放置你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"開發環境"},{"type":"text","text":" 的位置。可以轉到你的主目錄,或者你想放你的項目的任何地方,不需要爲你的開發環境創建新文件夾。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"創建一個遠程倉庫"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在我們要創建一個 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" 並將倉庫的內容導入你的計算機。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我建議使用這個 Git 倉庫:(https:\/\/github.com\/UnseenWizzard\/git_training.git)."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏可以使用這條命令拉取倉庫代碼:"},{"type":"codeinline","content":[{"type":"text","text":"git clone https:\/\/github.com\/UnseenWizzard\/git_training.git"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來的操作需要你將本地開發環境的改動提交到遠程倉庫,由於這個示例倉庫不允許他人操作,因此建議你將這個倉庫fork到你個人的github下,這個fork按鈕位於頁面的右上角."}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在,在你自己的github中已經有了這個_遠程倉庫_的副本,然後就可以將它克隆到你本地開發環境中了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以使用這條命令:"},{"type":"codeinline","content":[{"type":"text","text":"git clone https:\/\/github.com\/{YOUR USERNAME}\/git_training.git"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如下圖所示,這個遠程倉庫已經被拷貝到了兩個位置,即你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在你可以看到git是如何進行 "},{"type":"text","marks":[{"type":"italic"}],"text":"分佈式"},{"type":"text","text":" 版本控制的。"},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 是 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" 的副本,其行爲與之類似,唯一的區別是你沒有與任何人分享。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"git clone"}]},{"type":"text","text":" 還在你執行該命令的目錄下創建了一個新的文件夾. 這裏對應的應該是 "},{"type":"codeinline","content":[{"type":"text","text":"git_training"}]},{"type":"text","text":",打開它。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/62\/62ebdc54ee3d31f1d1b06905d858511c.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"添加一些新內容"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有人已經把"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"添加進了 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" 。她看上去有點孤單,所以讓我們創建一個"},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"去陪陪她。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這一步就是將文件添加到你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在在你的工作目錄中有兩種文件,一種是git知道的 "},{"type":"text","marks":[{"type":"italic"}],"text":"跟蹤文件"},{"type":"text","text":" ,另一種是git不知道的 "},{"type":"text","marks":[{"type":"italic"}],"text":"未跟蹤文件"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要查看你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 中發生了什麼,請運行"},{"type":"codeinline","content":[{"type":"text","text":"git status"}]},{"type":"text","text":",它將告訴你當前所處的分支、你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 是否與 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" 不同,以及 "},{"type":"text","marks":[{"type":"italic"}],"text":"跟蹤"},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"italic"}],"text":"未跟蹤"},{"type":"text","text":" 文件的狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你會看到"},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"是未跟蹤的,此外"},{"type":"codeinline","content":[{"type":"text","text":"git status"}]},{"type":"text","text":" 還會告訴你如何更改它。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在下面的圖片中,你可以看到當你根據建議執行"},{"type":"codeinline","content":[{"type":"text","text":"git add Bob.txt"}]},{"type":"text","text":"時會發生什麼:你已將該文件添加到 "},{"type":"text","marks":[{"type":"italic"}],"text":"暫存區"},{"type":"text","text":" ,該區域用於存放你希望放入倉庫的所有更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/d8\/d87ac83f07b726fd244cb048a991e241.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你添加了所有的更改(現在只添加了Bob)後,就可以將剛纔所做的操作提交到 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你提交的改動具有一定的意義,因此當你執行"},{"type":"codeinline","content":[{"type":"text","text":"git commit"}]},{"type":"text","text":"時,文本編輯器將打開,並允許你編寫一條消息,告訴他人你剛纔所做改動的意義。當你保存並關閉時,你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"提交"},{"type":"text","text":" 將被添加到 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/3c\/3c58b6d5fb3ff41eac24152f8825facb.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同樣你也可以直接在命令行中編輯你的commit 信息,比如:"},{"type":"codeinline","content":[{"type":"text","text":"git commit -m \"Add Bob\""}]},{"type":"text","text":"。如果你想寫出更規範化的commit信息,你可以花時間看看 good commit messages。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在,你的更改已經提交到了本地倉庫中,只要沒有其他人需要這些更改,或者你還沒有準備共享它們,就可以將這些更改保存在本地倉庫中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果需要通過 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" 共享你提交的改動,你需要"},{"type":"codeinline","content":[{"type":"text","text":"push"}]},{"type":"text","text":"它們。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/71\/71c19b278565334a7f2d8666612f94ef.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一旦運行"},{"type":"codeinline","content":[{"type":"text","text":"git push"}]},{"type":"text","text":",你的改動將被推送到   "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" ,"},{"type":"codeinline","content":[{"type":"text","text":"push"}]},{"type":"text","text":"之後的狀態如下圖所示。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0c\/0ce50d30c14bb2e0a76af1b27022b027.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"修改內容"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到目前爲止,我們只是添加了一個新文件。顯然,版本控制中更有趣的部分是更改文件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"中包含了一些文本,但是 "},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"是空的,所以讓我們在"},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"中加上"},{"type":"codeinline","content":[{"type":"text","text":"Hi!! I'm Bob. I'm new here."}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你現在執行 "},{"type":"codeinline","content":[{"type":"text","text":"git status"}]},{"type":"text","text":", 你會看到 "},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":" 已經更新了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此時這些改動僅僅位於你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你想看看你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 中發生了什麼更改,運行"},{"type":"codeinline","content":[{"type":"text","text":"git diff"}]},{"type":"text","text":",便可以看到如下內容:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"diff --git a\/Bob.txt b\/Bob.txt\nindex e69de29..3ed0e1b 100644\n--- a\/Bob.txt\n+++ b\/Bob.txt\n@@ -0,0 +1 @@\n+Hi!! I'm Bob. I'm new here."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"像之前那樣繼續執行 "},{"type":"codeinline","content":[{"type":"text","text":"git add Bob.txt"}]},{"type":"text","text":" 。這些改動則被移到了 "},{"type":"text","marks":[{"type":"italic"}],"text":"暫存區"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果想看看剛剛發生的改動,再次執行"},{"type":"codeinline","content":[{"type":"text","text":"git diff"}]},{"type":"text","text":" !你會注意到這次控制檯輸出是空的。這是因爲"},{"type":"codeinline","content":[{"type":"text","text":"git diff"}]},{"type":"text","text":"只會展示你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 中的更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了顯示哪些更改已經被暫存,執行"},{"type":"codeinline","content":[{"type":"text","text":"git diff --staged"}]},{"type":"text","text":",我們將看到與之前類似的輸出。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我剛注意到我們在\"Hi\"後面加了兩個感嘆號“!!”。我不喜歡這樣,讓我們再次修改"},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"文件將它改成'Hi!'。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果現在運行 "},{"type":"codeinline","content":[{"type":"text","text":"git status"}]},{"type":"text","text":",我們將看到有兩個更改:一個是我們已經 "},{"type":"text","marks":[{"type":"italic"}],"text":"暫存"},{"type":"text","text":" 的,另一個是我們剛剛做的,它還只保存在 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以執行"},{"type":"codeinline","content":[{"type":"text","text":"git diff"}]},{"type":"text","text":"來查看一下 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"italic"}],"text":"暫存區"},{"type":"text","text":" 在我們修改後都發生了什麼變化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"diff --git a\/Bob.txt b\/Bob.txt\nindex 8eb57c4..3ed0e1b 100644\n--- a\/Bob.txt\n+++ b\/Bob.txt\n@@ -1 +1 @@\n-Hi!! I'm Bob. I'm new here.\n+Hi! I'm Bob. I'm new here.\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於這是我們想要的改動,因此這裏執行"},{"type":"codeinline","content":[{"type":"text","text":"git add Bob.txt"}]},{"type":"text","text":" 去暫存這個文件當前的狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在我們可以提交剛剛的改動了。這裏我選擇直接命令行執行 "},{"type":"codeinline","content":[{"type":"text","text":"git commit -m \"Add text to Bob\""}]},{"type":"text","text":"。對這種小的變化,寫一行commit信息就夠了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如我們所知,這些改動現在是在 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 中。我們可能還想知道我們剛剛的提交,以及之前在 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 提交過的改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以通過比較這些commit來做到這一點。git中的每個commit都有一個唯一的哈希值作爲他的引用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們執行一下 "},{"type":"codeinline","content":[{"type":"text","text":"git log"}]},{"type":"text","text":",我們不僅可以看到所有提交的列表,包括它們的hash、Author和Date,還可以看到本地倉庫的狀態和遠程分支的最新本地信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"執行"},{"type":"codeinline","content":[{"type":"text","text":"git log"}]},{"type":"text","text":"後結果如下所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"commit 87a4ad48d55e5280aa608cd79e8bce5e13f318dc (HEAD -> master)\nAuthor: {YOU} \nDate: Sun Jan 27 14:02:48 2019 +0100\n\n Add text to Bob\n\ncommit 8af2ff2a8f7c51e2e52402ecb7332aec39ed540e (origin\/master, origin\/HEAD)\nAuthor: {YOU} \nDate: Sun Jan 27 13:35:41 2019 +0100\n\n Add Bob\n\ncommit 71a6a9b299b21e68f9b0c61247379432a0b6007c\nAuthor: UnseenWizzard \nDate: Fri Jan 25 20:06:57 2019 +0100\n\n Add Alice\n\ncommit ddb869a0c154f6798f0caae567074aecdfa58c46\nAuthor: Nico Riedmann \nDate: Fri Jan 25 19:25:23 2019 +0100\n\n Add Tutorial Text\n\n Changes to the tutorial are all squashed into this commit on master, to keep the log free of clutter that distracts from the tutorial\n\n See the tutorial_wip branch for the actual commit history"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏我們看到一些有趣的事情:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前兩次提交是我做的。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在遠程倉庫中,你最初添加Bob的提交是在HEAD指針指向的master分支上。在討論分支和獲取遠程更改時,我們將再次討論這個問題。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本地倉庫中最新的提交是我們剛剛做的,現在我們知道了它的哈希值。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"請注意,你實際的commit的哈希值可能與之不同。如果你想知道git具體是如何精確制定這些IDs的,請閱讀 this interesting article."}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要比較這個提交和之前的一個提交,可以執行 "},{"type":"codeinline","content":[{"type":"text","text":"git diff ^!"}]},{"type":"text","text":" (這裏的"},{"type":"codeinline","content":[{"type":"text","text":"^!"}]},{"type":"text","text":" 會告訴git去和它之前的一個提交比較)。在這裏我們執行 "},{"type":"codeinline","content":[{"type":"text","text":"git diff "}]},{"type":"codeinline","content":[{"type":"text","text":"87a4ad48d55e5280aa608cd79e8bce5e13f318dc^!"}]},{"type":"text","text":"."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們也可以執行 "},{"type":"codeinline","content":[{"type":"text","text":"git diff 8af2ff2a8f7c51e2e52402ecb7332aec39ed540e 87a4ad48d55e5280aa608cd79e8bce5e13f318dc"}]},{"type":"text","text":" 去比較任意兩個commit提交。請注意這裏的格式是"},{"type":"codeinline","content":[{"type":"text","text":"git diff "}]},{"type":"text","text":", 也就是說我們新的提交是後面這個。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在下面的圖表中,你會再次看到在不同git命令操作時,當前文件的的不同狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/3c\/3ceb2cb62e13d8c8b1cc8319112eef52.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"既然我們確定這些改動是符合預期的,那麼請繼續執行"},{"type":"codeinline","content":[{"type":"text","text":"git push"}]},{"type":"text","text":"吧。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"分支"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"git中分支的應用是不可或缺的一部分,這同時也是git之所以強大的原因之一。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實從一開始,我們就已經在使用分支了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你將遠程倉庫"},{"type":"codeinline","content":[{"type":"text","text":"clone"}]},{"type":"text","text":"到你的開發環境時,它已經自動創建了一個主分支:"},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你將改動 "},{"type":"codeinline","content":[{"type":"text","text":"合併"}]},{"type":"text","text":" 到 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 之前,git的大多數工作流程都是在一個分支上進行更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通常你都會在自己的分支上工作,直到你完成工作並確認無誤後,再將這些更改合併到 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"許多git倉庫管理器如 "},{"type":"text","marks":[{"type":"italic"}],"text":"GitLab"},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"italic"}],"text":"GitHub"},{"type":"text","text":" 還支持將分支保護起來, 即不允許任何人在此分支上提交改動。通常 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":"  分支是默認受保護的。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"別擔心,當我們需要這些內容時,我們再更詳細地討論。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你只想自己嘗試一些事情,而不是修改 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 分支的狀態,或者是你無權修改 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 時,你可以自己創建一個分支並對其進行一些更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分支是位於 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" 中的。當你創建新分支時,分支的內容將是當前正在處理的分支的提交狀態的副本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我們在 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"做一些改動! 不如在第二行放些文字怎麼樣?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們希望共享這個改動,但不希望提交到 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" ,因此可執行命令"},{"type":"codeinline","content":[{"type":"text","text":"git branch "}]},{"type":"text","text":" 來創建一個分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"創建一個名爲 "},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"的分支,你可以執行"},{"type":"codeinline","content":[{"type":"text","text":"git branch change_alice"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這條命令會在你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 下添加一個新分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"italic"}],"text":"暫存區"},{"type":"text","text":" 並不真正關心分支,但其實你的"},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":"操作總是將改動提交到當前所在的分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可以將git中的 "},{"type":"text","marks":[{"type":"italic"}],"text":"分支"},{"type":"text","text":" 視作很多指針,他們指向一系列的提交。當 執行"},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":"時,會添加到你當前指針指向的地方。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"只是添加一個分支,並不能直接把你帶到那裏,它只是創建一個這樣的指針。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實際上,你當前所處的 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" 可以看作另一個指針,稱爲 "},{"type":"text","marks":[{"type":"italic"}],"text":"HEAD"},{"type":"text","text":",它指向你當前所在的分支和提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果這聽起來很複雜,下面的圖表將有助於理清一些思緒:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/43\/43124969178a4a80ee8785e1a2308feb.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要切換到我們的新分支,你必須使用"},{"type":"codeinline","content":[{"type":"text","text":"git checkout change_alice"}]},{"type":"text","text":"。這隻需將 "},{"type":"text","marks":[{"type":"italic"}],"text":"HEAD"},{"type":"text","text":" 移動到你所指定的分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通常你都希望在創建分支後立即切換到該分支,因此"},{"type":"codeinline","content":[{"type":"text","text":"checkout"}]},{"type":"text","text":" 命令有一個方便的"},{"type":"codeinline","content":[{"type":"text","text":"-b"}]},{"type":"text","text":" 選項,它允許你直接"},{"type":"codeinline","content":[{"type":"text","text":"checkout"}]},{"type":"text","text":"一個新的分支而不必事先創建它。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,創建並切換一個 "},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":" 分支, 我們可以執行 "},{"type":"codeinline","content":[{"type":"text","text":"git checkout -b change_alice"}]},{"type":"text","text":"."}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/23\/232d0fdd6a29d2a591e40504cbc979e7.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你將發現,你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 沒有改變, 實際上我們 "},{"type":"text","marks":[{"type":"italic"}],"text":"修改"},{"type":"text","text":" "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":" 與當前分支無關。現在你可以像之前在master分支上那樣,執行 "},{"type":"codeinline","content":[{"type":"text","text":"add"}]},{"type":"text","text":" 及 "},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":"去提交我們在"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"上的改動,這將會暫存並最終將改動提交到"},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"分支上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在只有一件事你還沒有做,就是去執行"},{"type":"codeinline","content":[{"type":"text","text":"git push"}]},{"type":"text","text":"將你的改動提交到遠程倉庫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你將會看到下面的錯誤日誌以及解決這個問題的建議:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"fatal: The current branch change_alice has no upstream branch.\nTo push the current branch and set the remote as upstream, use\n(當前分支change_alice沒有上游分支,要推送當前分支的改動並設置遠端作爲上游分支,可以使用如下命令行:)\n\n git push --set-upstream origin change_alice\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看到這裏,我們不想根據提示盲目照做。我們是來了解實際情況的,那麼什麼是 上游分支 和 遠端分支?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還記得之前我們 "},{"type":"codeinline","content":[{"type":"text","text":"cloned"}]},{"type":"text","text":"遠程倉庫嗎?當時倉庫內容不僅包含本教程和 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"文件 ,實際上還有兩個分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個是我們剛開始在上面操作的 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" ,還有一個我命名爲\"tutorial_wip\"的分支,在這個分支上,我提交了本教程所做的所有更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當我們將遠程倉庫中的內容複製到你的開發環境中時,還進行了一些額外的操作,如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Git將本地倉庫的遠程倉庫設置爲克隆的遠程倉庫,默認名稱爲 "},{"type":"codeinline","content":[{"type":"text","text":"origin"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的本地倉庫可以跟蹤多個遠程,它們可以有不同的名稱,但本教程中我們使用的是"},{"type":"codeinline","content":[{"type":"text","text":"origin"}]},{"type":"text","text":" 。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後它將兩個遠程分支複製到你的本地倉庫,最後爲你切換到了master。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這時候另一個隱含的步驟發生了。當你"},{"type":"codeinline","content":[{"type":"text","text":"切換"}]},{"type":"text","text":" 一個與遠程分支完全匹配的分支名稱時,你將獲得一個新的鏈接到遠程分支的本地分支。這個遠程分支就是你這個本地分支的 "},{"type":"text","marks":[{"type":"italic"}],"text":"上游分支"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在前面的圖表中,你可以看到你擁有的本地分支。你可以通過運行"},{"type":"codeinline","content":[{"type":"text","text":"git branch"}]},{"type":"text","text":"查看本地分支的列表。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果還想查看你本地倉庫知道的遠程分支,可以使用 "},{"type":"codeinline","content":[{"type":"text","text":"git branch -a"}]},{"type":"text","text":" 列出所有分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/11\/11f6de2133fb295e1f5d4fd4f1b73ed7.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在我們可以執行之前命令窗口建議的"},{"type":"codeinline","content":[{"type":"text","text":"git push --set-upstream origin change_alice"}]},{"type":"text","text":"命令了,將分支上的更改 "},{"type":"codeinline","content":[{"type":"text","text":"push"}]},{"type":"text","text":" 到一個新的遠程節點上。這將在遠程倉庫上創建一個 "},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"分支,並會將我們的本地的 "},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"分支跟蹤該新的遠程分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們希望本地分支跟蹤遠程倉庫上已經存在一個分支,還有另一個選擇。也許一位同事已經推動了一些改動,而我們本地分支也解決了一些問題,我們希望將兩者結合起來。那麼,我們就可以通過使用"},{"type":"codeinline","content":[{"type":"text","text":"git branch --set-upstream-to=origin\/change_alice"}]},{"type":"text","text":",將"},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"分支的上游分支設置爲一個新的遠程分支,然後跟蹤這個遠程分支。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這之後,在github上查看一下你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程倉庫"},{"type":"text","text":" ,你的分支已經在那裏了,可以供其他人查看和使用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來,我們將瞭解如何將其他人的改動引入到你的開發環境中,但首先我們需要更多地練習使用分支,學習從遠程倉庫獲取改動也會用到的一些概念。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"合併"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於你和其他人通常都在各自分支上工作,所以我們需要討論如何通過合併這些分支來將更改從一個分支轉移到另一個分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們剛剛在"},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":" 分支上改變了 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":", 我對我們做的改動很滿意."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你執行"},{"type":"codeinline","content":[{"type":"text","text":"git checkout master"}]},{"type":"text","text":", 那麼我們在另一個分支上的"},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":" 將不存在。要將這些改動更新到 master中,我們需要將"},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"分支合併進 master."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"請注意,合併總是會將一個特定的分支合併到你當前所在的分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"快進合併"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們已經執行"},{"type":"codeinline","content":[{"type":"text","text":"checked out"}]},{"type":"text","text":"切換到了 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":", 那便可以合併分支了:"},{"type":"codeinline","content":[{"type":"text","text":"git merge change_alice"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"文件中沒有其他的衝突改動,並且我們在master上也沒有任何改動,這便稱之爲快進合併。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在下面的圖表中,你可以看到快進合併意味着 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 的指針簡單地移動到"},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"所在的位置。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一張圖顯示了"},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":"之前的狀態,"},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 仍然處於最初的提交狀態,而在另一個分支上,我們又進行了一次提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/28\/288f5d99a92d8678c52998c1fea5edd3.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二張圖顯示了 "},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":"之後的狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/8b\/8b0422b704097644515b31e5dc31b577.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"合併衝突分支"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我們試試更復雜的東西。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 分支上給 "},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"添加一些文本並提交它。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後執行"},{"type":"codeinline","content":[{"type":"text","text":"git checkout change_alice"}]},{"type":"text","text":"切換分支修改"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"文件並提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在下面的圖表中,你可以看到我們的提交歷史。"},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 和 "},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":" 都源於同一個commit,但從那時起,它們就分開了,每個分支都有自己的附加提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/01\/017decc398c5ec9927beed29f6132f96.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果現在切換回master(git checkout master)並執行"},{"type":"codeinline","content":[{"type":"text","text":"git merge change_alice"}]},{"type":"text","text":" 則無法進行快速合併。此時,文本編輯器將打開並需要你更改"},{"type":"codeinline","content":[{"type":"text","text":"merge commit"}]},{"type":"text","text":"的消息,以便將兩個分支重新合併在一起,這裏你可以使用默認消息。下面的圖表顯示了我們在 "},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":"之後git歷史的狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/03\/0391f2eac0eb44e53f8958abf39987c3.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個新提交將我們在"},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"分支上所做的更改引入到了master中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如你以前所記得的,git中的修訂不僅是文件的快照,還包含文件的來源信息。每個 "},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":"都有一個或多個父提交。我們新的 "},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":"提交,既有來自_master_ 的最後一次提交,也有我們在另一個分支上作爲其父級所做的提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"解決衝突"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到目前爲止,我們的改動還沒有相互干擾。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我們製造一個 "},{"type":"text","marks":[{"type":"italic"}],"text":"衝突"},{"type":"text","text":" 然後 "},{"type":"text","marks":[{"type":"italic"}],"text":"解決"},{"type":"text","text":" 它吧。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"創建並切換到一個新的分支,這個你已經知道怎麼做了,也可以簡單地執行"},{"type":"codeinline","content":[{"type":"text","text":"git checkout -b"}]},{"type":"text","text":",這裏我們將新分支命名爲"},{"type":"codeinline","content":[{"type":"text","text":"bobby_branch"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基於這個分支,我們在"},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"文件上做一些改動。現在第一行應該還是"},{"type":"codeinline","content":[{"type":"text","text":"Hi!! I'm Bob. I'm new here."}]},{"type":"text","text":",我們將它改成 "},{"type":"codeinline","content":[{"type":"text","text":"Hi!! I'm Bobby. I'm new here."}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"保留並提交你的改動之後,切換到master分支。我們修改同樣的這行內容爲 "},{"type":"codeinline","content":[{"type":"text","text":"Hi!! I'm Bob. I've been here for a while now."}]},{"type":"text","text":",然後提交這個改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在再將你的新分支合到master分支上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你嘗試這麼做的時候,你會看到下面這樣的提示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"Auto-merging Bob.txt\nCONFLICT (content): Merge conflict in Bob.txt\nAutomatic merge failed; fix conflicts and then commit the result.\n(自動合併Bob.txt發生衝突(內容):Bob.txt文件衝突自動合併失敗;修復衝突然後提交結果。)\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"兩個分支都修改了同樣的一行內容,git無法自動處理這樣的改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你執行"},{"type":"codeinline","content":[{"type":"text","text":"git status"}]},{"type":"text","text":" ,你將會得到如何繼續下一步的一些有幫助的指令。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先我們必須手動解決衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於像這樣簡單的衝突來說,你的文本編輯器就可以做到。但對於有大量文件的改動來說,一個功能強大的編輯工具會讓你的工作變的更簡單,我建議你的編輯器最好帶有版本控制工具和很好的合併視圖窗口。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你在編輯器中打開文件,你會看到類似下面這樣的內容(這裏我只截取了之前在第二行中添加的內容):"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"<<<<<<>>>>>> bobby_branch\n[... whatever you've put on line 2]\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在最上面你可以看到 "},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":" 在當前 HEAD上的改動,下面是我們合併進的分支中發生的改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要手動解決衝突,你只需要確保最終保留你所需的內容,並且刪掉git在文件中引入的特殊行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以繼續把文件改成這樣:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"Hi! I'm Bobby. I've been here for a while now.\n[...]\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏所做的改動是我們所需要的,因此執行"},{"type":"codeinline","content":[{"type":"text","text":"add Bob.txt"}]},{"type":"text","text":"暫存這個文件,再 "},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":"提交."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們已經知道這次提交是爲解決衝突所做的。這就是在合併提交時經常出現的 "},{"type":"text","marks":[{"type":"italic"}],"text":"merge commit"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你在解決衝突的過程中意識到你實際上不想使用"},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":",你可以通過運行 "},{"type":"codeinline","content":[{"type":"text","text":"git merge --abort"}]},{"type":"text","text":"來 "},{"type":"codeinline","content":[{"type":"text","text":"中止"}]},{"type":"text","text":" 它。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"變基"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Git有另一種清晰的方法來集成兩個分支之間的更改,稱爲 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"變基。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們仍然記得,一個分支總是基於另一個分支。當你創建它的時候,你就從某個地方檢出了一個分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在剛剛簡單合併的示例中,我們在一個特定的commit節點從 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 檢出了一個分支,然後在 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 和 "},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":" 分支上都提交了一些更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當一個分支與它所基於的分支發生分歧,並且你希望將最新的更改重新集成到當前分支中時, "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 提供了一種比 "},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":" 更簡潔的方法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如我們所看到的,"},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":" 引入了一個 "},{"type":"text","marks":[{"type":"italic"}],"text":"merge commit"},{"type":"text","text":" ,其中兩個歷史記錄再次集成在一起。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"簡單地說,變基只會改變分支所基於的歷史點(commit節點)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲此,讓我們再次切換到master分支,然後基於它創建\/簽出一個新分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們給它取名 "},{"type":"codeinline","content":[{"type":"text","text":"add_patrick"}]},{"type":"text","text":",在這個分支上加了一個新的文件"},{"type":"codeinline","content":[{"type":"text","text":"Patrick.txt"}]},{"type":"text","text":"然後提交,並附上提交信息:'Add Patrick'。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你在這個分支添加提交後,切回到 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" ,同樣進行更改並提交。這裏我在"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"文件裏添加了一些文本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就像在我們的合併示例中,這兩個分支的歷史在一個共同的祖先處發生了分歧,如下圖所示。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/84\/841ce1b655a645c900193d34342fcf65.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在讓我再次執行"},{"type":"codeinline","content":[{"type":"text","text":"checkout add_patrick"}]},{"type":"text","text":", 並將在 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 上所做的更改添加到我們正在處理的分支中!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當我們執行 "},{"type":"codeinline","content":[{"type":"text","text":"git rebase master"}]},{"type":"text","text":", 我們將"},{"type":"codeinline","content":[{"type":"text","text":"add_patrick"}]},{"type":"text","text":"分支修改爲基於當前 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 分支的狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"命令行的輸出提示很好的告訴了我們發生了什麼:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"First, rewinding head to replay your work on top of it...\n(首先,倒回頭部,重新將你的工作放置在他的開頭...)\nApplying: Add Patrick\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們還記得,在我們的開發環境中, "},{"type":"text","marks":[{"type":"italic"}],"text":"HEAD"},{"type":"text","text":" 指向的是當前提交的指針。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在變基開始之前,它和"},{"type":"codeinline","content":[{"type":"text","text":"add_patrick"}]},{"type":"text","text":" 指向的是同一個地方。變基的過程中,它首先移動回共同的祖先處,然後移動到我們想要重新建立的分支的頭部。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此, "},{"type":"text","marks":[{"type":"italic"}],"text":"HEAD"},{"type":"text","text":" 從 "},{"type":"text","marks":[{"type":"italic"}],"text":"0cfc1d2"},{"type":"text","text":" 的提交移動到位於 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 頭部的 "},{"type":"text","marks":[{"type":"italic"}],"text":"7639f4b"},{"type":"text","text":" 提交處。然後變基會將我們在 "},{"type":"codeinline","content":[{"type":"text","text":"add_patrick"}]},{"type":"text","text":" 分支上所做的每一次提交都應用到該分支中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"更確切地說, "},{"type":"text","marks":[{"type":"italic"}],"text":"git"},{"type":"text","text":" 在 "},{"type":"text","marks":[{"type":"italic"}],"text":"HEAD"},{"type":"text","text":" 移回分支的共同祖先之後,會存儲你在分支上所做的每一次提交(包括不同的改動,以及提交文本、作者等)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之後,它會切換到你基於它創建的新分支,然後將存儲的所有改動在你的新分支上作一個新的提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,在我們最初的簡化視圖中,可以假設在 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 之後, "},{"type":"text","marks":[{"type":"italic"}],"text":"0cfc1d2"},{"type":"text","text":" 提交不再指向歷史上的共同祖先,而是指向了 master的頭部。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"事實上,"},{"type":"text","marks":[{"type":"italic"}],"text":"0cfc1d2"},{"type":"text","text":" 提交已經不存在了,"},{"type":"codeinline","content":[{"type":"text","text":"add_patrick"}]},{"type":"text","text":" 分支以一個新的 "},{"type":"text","marks":[{"type":"italic"}],"text":"0ccaba8"},{"type":"text","text":" 提交開始,它的祖先是 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 的最新提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它看起來,就像我們的 "},{"type":"codeinline","content":[{"type":"text","text":"add_patrick"}]},{"type":"text","text":" 是基於當前的 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":",而不是它的舊版本,其實在這裏我們重新書寫了分支的歷史。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在本教程的最後,我們將學習更多關於重寫歷史的知識,以及什麼時候適合這樣做,什麼時候不適合。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/f3\/f3335758205d9b3b8ea999753270a4ae.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你基於一個共享的分支,如 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 檢出一個自己的開發分支,在上面工作時,"},{"type":"codeinline","content":[{"type":"text","text":"Rebase"}]},{"type":"text","text":" 是一個非常強大的工具。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用"},{"type":"codeinline","content":[{"type":"text","text":"Rebase"}]},{"type":"text","text":",有助於你經常整合其他人所做的更改並將其推送到 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" ,同時保持一個清晰的線性歷史記錄,以便在需要將你的改動作放入共享分支時進行 "},{"type":"codeinline","content":[{"type":"text","text":"fast-forward merge"}]},{"type":"text","text":" 快進合併。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"保持線性的歷史記錄在查看提交日誌時比使用 "},{"type":"text","marks":[{"type":"italic"}],"text":"merge commits"},{"type":"text","text":" 混合提交(通常只使用默認文本)更有用。(可以嘗試 "},{"type":"codeinline","content":[{"type":"text","text":"git log --graph"}]},{"type":"text","text":" 或查看 "},{"type":"text","marks":[{"type":"italic"}],"text":"GitHub"},{"type":"text","text":" or "},{"type":"text","marks":[{"type":"italic"}],"text":"GitLab"},{"type":"text","text":" 的分支視圖)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"解決衝突"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在使用"},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":"合併分支時,如果兩個提交更改了文件的同一個部分,則可能會發生衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,當你在"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 時遇到衝突時,你不會在額外的 "},{"type":"text","marks":[{"type":"italic"}],"text":"merge commit"},{"type":"text","text":" 中修復它,而是在當前所在的提交中簡單地解決它。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同樣地,直接根據原始分支的當前狀態進行更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實際上,"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 解決衝突與 "},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":"的方法非常相似,如果你不記得怎麼做了,請回顧該部分內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"唯一的區別是,由於你沒有引入 "},{"type":"text","marks":[{"type":"italic"}],"text":"merge commit"},{"type":"text","text":" (合併提交),因此沒有必要提交你的解決方案。只需使用"},{"type":"codeinline","content":[{"type":"text","text":"add"}]},{"type":"text","text":" 將改動添加到暫存區,然後執行 "},{"type":"codeinline","content":[{"type":"text","text":"git rebase --continue"}]},{"type":"text","text":",衝突將在剛剛的提交中解決。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在合併時,當你執行 "},{"type":"codeinline","content":[{"type":"text","text":"git rebase --abort"}]},{"type":"text","text":"之前,你始終可以停止並放棄到目前爲止所做的一切。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"根據遠程倉庫更新本地開發環境"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到目前爲止,我們只學會瞭如何創建和分享我們的改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你剛剛做的所有操作通常也是其他人會做的,因此我們需要知道怎麼從遠程倉庫獲取到他們提交的改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"過了這麼久,讓我們再來回顧一下git的組件:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/24\/2464da0c7d496218ce816e2bb90970d6.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就像你的開發環境一樣,其他人也都有他們的開發環境。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/c0\/c0529bf5cf59898521c2a948f0830711.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所有這些開發環境中保留着他們自己的本地改動和暫存的改動,這些更改在某個時刻提交到他們的本地倉庫,最後被推送到遠程。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在下面的例子中,我們將使用 "},{"type":"text","marks":[{"type":"italic"}],"text":"GitHub"},{"type":"text","text":" 提供的在線工具來模擬其他人在我們工作時對 "},{"type":"text","marks":[{"type":"italic"}],"text":"remote"},{"type":"text","text":" (遠端)進行的更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"進入你通過 "},{"type":"codeinline","content":[{"type":"text","text":"fork"}]},{"type":"text","text":" 拷貝了此資源的github.com地址並且打開"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":" 文件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"找到編輯按鈕,進行更改,並直接通過網站提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/43\/4301a7038b07c6dc28ba78d1e9156e4d.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個庫中,我已在一個名爲"},{"type":"codeinline","content":[{"type":"text","text":"fetching_changes_sample"}]},{"type":"text","text":"的分支上將遠程更改添加到了"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":" ,但是在你的倉庫中,你可以直接在 "},{"type":"codeinline","content":[{"type":"text","text":"master"}]},{"type":"text","text":"分支上更改文件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"獲取改動"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們還記得,當你使用 "},{"type":"codeinline","content":[{"type":"text","text":"git push"}]},{"type":"text","text":"時,你會將本地倉庫的更改同步到遠程倉庫中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要把 "},{"type":"text","marks":[{"type":"italic"}],"text":"遠程"},{"type":"text","text":" 所做的更改保存到本地倉庫中,請使用 "},{"type":"codeinline","content":[{"type":"text","text":"git fetch"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這會將遠程服務器上的任何更改(包括提交和分支)保存到你的本地倉庫中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意,此時,更改還沒有集成到本地分支中,因此也還沒有集成到你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"italic"}],"text":"暫存區"},{"type":"text","text":" 中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/c8\/c8ee8e6acbdd41f7be59e5fe1cc33399.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果現在運行 "},{"type":"codeinline","content":[{"type":"text","text":"git status"}]},{"type":"text","text":" ,你將看到另一個很好的git命令示例,它告訴你到底發生了什麼:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"> git status\nOn branch fetching_changes_sample\nYour branch is behind 'origin\/fetching_changes_sample' by 1 commit, and can be fast-forwarded.\n (use \"git pull\" to update your local branch)\n\n在fetching_changes_sample分支上,你的分支落後於遠程的'origin\/fetching_changes_sample'一個提交,可以被快進合併\n(使用“git pull”命令去更新你的本地分支)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"拉取改動"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在我們的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 或 "},{"type":"text","marks":[{"type":"italic"}],"text":"暫存區"},{"type":"text","text":" 沒有改動時,我們可以執行 "},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":" 將來自遠程的更改拉取到我們的工作區。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Pulling拉取操作也會隱式地"},{"type":"codeinline","content":[{"type":"text","text":"fetch"}]},{"type":"text","text":"拉取 遠程倉庫,但有時單獨執行"},{"type":"codeinline","content":[{"type":"text","text":"fetch"}]},{"type":"text","text":"是個好主意。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"例如,當你要同步任何新的遠程分支時,或者你希望你在 "},{"type":"codeinline","content":[{"type":"text","text":"origin\/master"}]},{"type":"text","text":"分支上執行"},{"type":"codeinline","content":[{"type":"text","text":"git rebase"}]},{"type":"text","text":" 之前確保你的本地倉庫是最新的時候。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/99\/99df5c0b7832212a4f611cb34a282f1b.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在我們執行 "},{"type":"codeinline","content":[{"type":"text","text":"pull"}]},{"type":"text","text":"之前,讓我們改動一個本地文件看看會發生什麼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏我們同樣在本地工作區修改 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":" 文件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你現在試着執行 "},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":",你會看到下面這樣的報錯:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"> git pull\nUpdating df3ad1d..418e6f0\nerror: Your local changes to the following files would be overwritten by merge:\n Alice.txt\nPlease commit your changes or stash them before you merge.\n(錯誤:被跟蹤的本地文件alice.txt在合併時會被重寫,請在合併提交(commit)或存儲(stash)你的改動)\nAborting\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你無法拉取任何改動,因爲在你執行pull操作時,你的本地工作區間文件的改動會被這次提交重寫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此時其中一個方法是,在你最終提交這些本地改動前,將他們添加到一個儲藏區,這裏有一個好用的工具: "},{"type":"codeinline","content":[{"type":"text","text":"git stash"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"存儲改動"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果某些時候,你有不想放入commit中的本地改動,或者在嘗試以不同的角度解決問題時希望將其存儲在某個位置,則可以使用 "},{"type":"codeinline","content":[{"type":"text","text":"stash"}]},{"type":"text","text":"將這些更改儲藏起來。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"git stash"}]},{"type":"text","text":" 儲藏的基本上是你在 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 中做的一些更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可以使用命令 "},{"type":"codeinline","content":[{"type":"text","text":"git stash"}]},{"type":"text","text":"將工作目錄的任何修改放入儲藏區,然後使用命令"},{"type":"codeinline","content":[{"type":"text","text":"git stash pop"}]},{"type":"text","text":" 將最近儲藏的改動取出並再次應用在你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"工作目錄"},{"type":"text","text":" 上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如stash命令這個堆棧名字一樣,"},{"type":"codeinline","content":[{"type":"text","text":"git stash pop"}]},{"type":"text","text":" 命令會在再次應用之前刪除最新存儲的改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你希望保留儲藏的改動,你可以使用"},{"type":"codeinline","content":[{"type":"text","text":"git stash apply"}]},{"type":"text","text":",這樣在你應用更改之前便不會將其從堆棧中刪除。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要檢查當前已有的存儲,你可以使用 "},{"type":"codeinline","content":[{"type":"text","text":"git stash list"}]},{"type":"text","text":" 列出所有儲藏的條目,使用 "},{"type":"codeinline","content":[{"type":"text","text":"git stash show"}]},{"type":"text","text":" 顯示儲藏的最新的更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"另一個很便捷的命令是 "},{"type":"codeinline","content":[{"type":"text","text":"git stash branch {BRANCH NAME}"}]},{"type":"text","text":",它會從保存更改時的HEAD處創建一個分支,並將你準備儲藏的改動應用在這個分支上。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在我們知道了 "},{"type":"codeinline","content":[{"type":"text","text":"git stash"}]},{"type":"text","text":"的作用,讓我們運行它來刪除本地工作目錄中 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"的改動,這樣我們就可以繼續使用"},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":" 從遠程獲取更改了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後,再執行"},{"type":"codeinline","content":[{"type":"text","text":"git stash pop"}]},{"type":"text","text":" 把本地的改動取回。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲我們pull的遠程倉庫和儲藏的更改都修改了 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":" 文件,所以這裏需要解決衝突,就像前面 "},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":" 或"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"提到的那樣的做法來解決,然後通過 "},{"type":"codeinline","content":[{"type":"text","text":"add"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":"提交這次改動就好了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"拉取有衝突的內容"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在我們已經理解了怎麼通過 "},{"type":"codeinline","content":[{"type":"text","text":"fetch"}]},{"type":"text","text":" 和 "},{"type":"codeinline","content":[{"type":"text","text":"pull"}]},{"type":"text","text":"去拉取遠程改動到我們的開發環境,接下來讓我們去製造一些衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不用推送你改動的"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"文件,直接回到你的github.com上的遠程倉庫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏我們繼續修改"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"文件然後提交這次改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在,實際上在我們的本地和遠程倉庫已經有兩了個衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不要忘了執行"},{"type":"codeinline","content":[{"type":"text","text":"git fetch"}]},{"type":"text","text":"來查看遠程修改,而不是直接執行"},{"type":"codeinline","content":[{"type":"text","text":"pull"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你現在執行"},{"type":"codeinline","content":[{"type":"text","text":"git status"}]},{"type":"text","text":" 你會看到,這兩個分支上都有一處與另一個分支不同的改動"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"> git status\nOn branch fetching_changes_sample\nYour branch and 'origin\/fetching_changes_sample' have diverged,\nand have 1 and 1 different commits each, respectively.\n (use \"git pull\" to merge the remote branch into yours)\n分支fetching_changes_sample與origin\/fetching_changes_sample發生分歧,各自都有一次提交。\n(使用git pull 將遠程的分支合併進你的分支)\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此外,我們在兩個分支上都對同一個文件做了修改,從而製造出了這個需要我們解決的合併衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你執行"},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":",本地和遠程倉庫會發生衝突,這和之前合併兩個分支時出現的情況一樣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由此,你可以將遠程倉庫和本地倉庫出現的衝突當成是基於一個分支創建了另一個分支,這兩個分支出現衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本地分支是基於你上次 "},{"type":"codeinline","content":[{"type":"text","text":"fetched"}]},{"type":"text","text":" 拉取遠程分支時的狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從這個角度看,從獲取遠程改動要做的這兩個選擇是很有意義的:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你執行"},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":"時,本地和遠程分支會被合併。就像合併分支一樣,這裏會創建一個合併的commit提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲任何一個本地分支都是基於其各自的遠程版本,所以我們也可以對它進行"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"變基,這樣我們在本地所做的任何更改都會看起來像是基於遠程倉庫的最新改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲此,我們可以執行 "},{"type":"codeinline","content":[{"type":"text","text":"git pull --rebase"}]},{"type":"text","text":" (或者簡寫成 "},{"type":"codeinline","content":[{"type":"text","text":"git pull -r"}]},{"type":"text","text":")。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如變基一節中闡述的,保持一個清晰的歷史記錄很重要,這就是爲什麼我建議無論何時你執行"},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":",最好選擇執行"},{"type":"codeinline","content":[{"type":"text","text":"git pull -r"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你也可以告訴git在使用"},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":"用 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"而不是"},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":" 作爲它的默認方式,通過"},{"type":"codeinline","content":[{"type":"text","text":"pull.rebase"}]},{"type":"text","text":"指令如"},{"type":"codeinline","content":[{"type":"text","text":"git config --global pull.rebase true"}]},{"type":"text","text":"可完成設置。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你在我前幾段第一次提到獲取更新時已經執行了 "},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":",那麼現在可以運行"},{"type":"codeinline","content":[{"type":"text","text":"git pull -r"}]},{"type":"text","text":"來獲取遠程更改,這樣我們新的提交看起來像是在拉取了遠程之後才更新的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當然,就像使用"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"(或 "},{"type":"codeinline","content":[{"type":"text","text":"merge"}]},{"type":"text","text":")一樣,你也需要在 "},{"type":"codeinline","content":[{"type":"text","text":"git pull"}]},{"type":"text","text":"前解決引入的衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"揀選"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"恭喜你!你已經完成了更高級的功能!現在你已經瞭解瞭如何使用所有典型的git命令,以及它們是如何工作的。希望這有助於你理解下面要說的概念。接下來,讓我們開始學習如何揀選我們的提交吧!"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"回顧前面的章節內容,你應該還大致記得什麼是 "},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":" 提交,對吧?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以及當你"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"一個分支時,你的提交是怎麼帶着同樣的改動和信息作爲一個新的commit提交的?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"無論何時,只要你想從一個分支獲取一些更改並將它們應用到另一個分支,你都需要"},{"type":"codeinline","content":[{"type":"text","text":"cherry-pick"}]},{"type":"text","text":"揀選這些提交併將它們放到你的分支上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"git cherry-pick"}]},{"type":"text","text":" 允許你對單個提交或一系列提交執行操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就像 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 的過程一樣,這實際上會將這些提交的更改放入當前分支的新提交中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我們看一下有一個及多個提交時,執行"},{"type":"codeinline","content":[{"type":"text","text":"cherry-pick"}]},{"type":"text","text":"的示例。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下圖顯示了我們做任何操作之前的三個分支。假設我們想從"},{"type":"codeinline","content":[{"type":"text","text":"add_patrick"}]},{"type":"text","text":"分支獲取一些更改到 "},{"type":"codeinline","content":[{"type":"text","text":"change_alice"}]},{"type":"text","text":"分支。遺憾的是,它們都還沒有合進master,所以我們不能僅僅通過 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"來獲得這些更改(我們可能也不需要其他分支的其餘的改動)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/65\/655556ff431d7b1506ca86aae8955ea6.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此讓我們執行 "},{"type":"codeinline","content":[{"type":"text","text":"git cherry-pick"}]},{"type":"text","text":" 揀選 "},{"type":"text","marks":[{"type":"italic"}],"text":"63fc421"},{"type":"text","text":" 的這次提交. 下圖清晰地顯示了運行 "},{"type":"codeinline","content":[{"type":"text","text":"git cherry-pick 63fc421"}]},{"type":"text","text":"時發生的事情:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/cf\/cf02c3faa54d766ee85241c0f802a36d.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如你所見,分支上出現了一個新的帶着我們需要改動的commit提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這時請注意,就像我們之前所見的合併分支改動一樣,在執行下一步命令前,我們需要解決執行"},{"type":"codeinline","content":[{"type":"text","text":"cherry-pick"}]},{"type":"text","text":"時出現的任何衝突。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"解決完衝突後,和之前一樣,你可以繼續執行揀選"},{"type":"codeinline","content":[{"type":"text","text":"cherry-pick"}]},{"type":"text","text":",或者決定直接"},{"type":"codeinline","content":[{"type":"text","text":"--abort"}]},{"type":"text","text":"中止該命令。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下圖顯示了使用揀選("},{"type":"codeinline","content":[{"type":"text","text":"cherry-pick"}]},{"type":"text","text":")選擇一系列提交而不是單個提交。你只需調用形式爲"},{"type":"codeinline","content":[{"type":"text","text":"git cherry-pick .."}]},{"type":"text","text":"的命令,或者如下面的示例調用"},{"type":"codeinline","content":[{"type":"text","text":"git cherry-pick 0cfc1d2..41fbfa7"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/45\/4582d5684e19da0101eb0bd582305a26.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"改寫歷史"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我現在再問一遍,你還記得"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 嗎?不記得的話可以跳回去快速瀏覽一遍,因爲下面學習如何改寫歷史需要使用到這部分知識哦!"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你已經知道了一個基礎的commit提交包含了你的改動、提交信息和一些其他的內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所謂分支的'歷史' 就是由所有提交組成的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是假設你剛剛提交了一個"},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":",然後發現你忘了添加一個文件,或者你犯了一個錯誤,而這個改變給你留下了一個壞的代碼,怎麼辦呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種情況下,我們將簡要介紹兩種解決方式,使它看起來像從未發生過一樣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我們執行"},{"type":"codeinline","content":[{"type":"text","text":"git checkout -b rewrite_history"}]},{"type":"text","text":",切換到一個新的分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在讓我們在 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":" 和 "},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"文件中做一些改動,然後執行 "},{"type":"codeinline","content":[{"type":"text","text":"git add Alice.txt"}]},{"type":"text","text":"。然後帶上信息\"This is history\" 提交("},{"type":"codeinline","content":[{"type":"text","text":"git commit"}]},{"type":"text","text":")。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"等等,我剛剛做了什麼?你應該知道我剛剛做錯什麼了吧!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我忘了添加"},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"文件。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我也沒有提交一個友好的commit信息。(友好的書寫commit可見:good commit message)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"修改最後一次提交"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一次性解決這兩個問題的辦法是是修改("},{"type":"codeinline","content":[{"type":"text","text":"amend"}]},{"type":"text","text":" )我們剛剛提交的commit。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"修改最新的提交基本上就像創建一個新的提交一樣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在我們做任何事情之前,先看看你最近的提交("},{"type":"codeinline","content":[{"type":"text","text":"git show {COMMIT}"}]},{"type":"text","text":")。COMMIT中輸入commit的hash值(hash值可以通過調用命令行 "},{"type":"codeinline","content":[{"type":"text","text":"git commit"}]},{"type":"text","text":"或"},{"type":"codeinline","content":[{"type":"text","text":"git log"}]},{"type":"text","text":"看到),或者直接使用 "},{"type":"text","marks":[{"type":"italic"}],"text":"HEAD"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就像"},{"type":"codeinline","content":[{"type":"text","text":"git log"}]},{"type":"text","text":"打印出的結果一樣,你會看到消息、作者、日期,當然還有改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在讓我們修正我們在那次提交中所做的改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"執行"},{"type":"codeinline","content":[{"type":"text","text":"git add Bob.txt"}]},{"type":"text","text":"將改動添加到暫存區, 然後執行 "},{"type":"codeinline","content":[{"type":"text","text":"git commit --amend"}]},{"type":"text","text":"."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來你會看到最新的提交被展開,新的改動被添加到暫存區已有的改動中。commit提交消息的編輯器被打開。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在編輯器中,你將看到前面的提交消息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可以把它修改成更友好的提交信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"做完這些之後,執行"},{"type":"codeinline","content":[{"type":"text","text":"git show HEAD"}]},{"type":"text","text":"看一下最新的提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如你預期的那樣,提交的哈希改變了。原來的提交不見了,取而代之的是一個新的提交,它包含了組合後的更改和新的提交消息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"請注意其他提交數據(如author和date)與原始提交相比是保持不變的。如果需要,你也可以在修改時使用"},{"type":"codeinline","content":[{"type":"text","text":"--author={AUTHOR}"}]},{"type":"text","text":" 和"},{"type":"codeinline","content":[{"type":"text","text":"--date={DATE}"}]},{"type":"text","text":" 來修改。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"祝賀你!你第一次成功地改寫了歷史!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"交互式變基"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通常,當我們執行"},{"type":"codeinline","content":[{"type":"text","text":"git rebase"}]},{"type":"text","text":"時,我們變基到一個分支上。當我們執行"},{"type":"codeinline","content":[{"type":"text","text":"git rebase origin\/master"}]},{"type":"text","text":"之類的操作時,實際是將一個指針重新定位到到該分支的 "},{"type":"text","marks":[{"type":"italic"}],"text":"HEAD"},{"type":"text","text":" 指針上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"事實上只要我們喜歡,我們可以 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"變基到任何的commit上"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"請記住,提交包含了之前的歷史記錄"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"和許多其他命令一樣,"},{"type":"codeinline","content":[{"type":"text","text":"git rebase"}]},{"type":"text","text":"有一個“交互式”模式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"與其他大多數命令不同的是,交互式的 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"可能是你經常使用的東西,因爲它允許你隨意改變歷史。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"尤其是如果你的更改有許多的小提交,這樣一旦你犯了錯誤,你可以很容易地跳回原位,那麼交互式的 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 將是你最親密的盟友。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"話不多說!讓我們做點什麼吧!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"切換回你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 分支,然後執行"},{"type":"codeinline","content":[{"type":"text","text":"git checkout"}]},{"type":"text","text":" 檢出一個新分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"像之前一樣,我們會在"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"和 "},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"文件上做一些更改,然後添加"},{"type":"codeinline","content":[{"type":"text","text":"git add Alice.txt"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後我們執行 "},{"type":"codeinline","content":[{"type":"text","text":"git commit"}]},{"type":"text","text":"來提交它,提交信息可以是\"Add text to Alice\""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在不改變那次提交,我們繼續執行"},{"type":"codeinline","content":[{"type":"text","text":"git add Bob.txt"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"git commit"}]},{"type":"text","text":",這裏我用的提交信息是\"Add Bob.txt\""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了讓事情變得更有趣,我們在"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"文件上做一些改動,然後提交:執行"},{"type":"codeinline","content":[{"type":"text","text":"git add"}]},{"type":"text","text":" 和"},{"type":"codeinline","content":[{"type":"text","text":"git commit"}]},{"type":"text","text":",帶上提交信息\"Add more text to Alice\"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們現在執行"},{"type":"codeinline","content":[{"type":"text","text":"git log"}]},{"type":"text","text":"查看一下分支歷史(或者也可以用"},{"type":"codeinline","content":[{"type":"text","text":"git log --oneline"}]},{"type":"text","text":"快速的查看一下),我們將看到在 "},{"type":"text","marks":[{"type":"italic"}],"text":"master"},{"type":"text","text":" 上的三個提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我這邊看起來是這樣的:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"> git log --oneline\n0b22064 (HEAD -> interactiveRebase) Add more text to Alice\n062ef13 Add Bob.txt\n9e06fca Add text to Alice\ndf3ad1d (origin\/master, origin\/HEAD, master) Add Alice\n800a947 Add Tutorial Text\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們想做下面兩件事情,爲了學習不同的內容,這將有點不同於上一節的"},{"type":"codeinline","content":[{"type":"text","text":"amend"}]},{"type":"text","text":":"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"將"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"的兩次改動作爲一次commit提交"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"保持修改bob文件那次commit信息中bob的名字,將"},{"type":"codeinline","content":[{"type":"text","text":"Bob.txt"}]},{"type":"text","text":"後面的 "},{"type":"text","marks":[{"type":"italic"}],"text":".txt"},{"type":"text","text":" 信息去掉。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要更改這三個新提交,我們需要重新定位到它們之前的提交。對我來說,這個提交hash值是"},{"type":"codeinline","content":[{"type":"text","text":"df3ad1d"}]},{"type":"text","text":",但是我們也可以引用當前 "},{"type":"text","marks":[{"type":"italic"}],"text":"HEAD"},{"type":"text","text":" 的往前第三次提交:"},{"type":"codeinline","content":[{"type":"text","text":"HEAD~3"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要啓動一個交互式的"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":",我們使用"},{"type":"codeinline","content":[{"type":"text","text":"git rebase -i {COMMIT}"}]},{"type":"text","text":", 這裏執行的是 "},{"type":"codeinline","content":[{"type":"text","text":"git rebase -i HEAD~3"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你將看到你選擇的編輯器顯示如下內容:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"pick 9e06fca Add text to Alice\npick 062ef13 Add Bob.txt\npick 0b22064 Add more text to Alice\n\n# Rebase df3ad1d..0b22064 onto df3ad1d (3 commands)\n#\n# Commands:\n# p, pick = use commit\n# r, reword = use commit, but edit the commit message\n# e, edit = use commit, but stop for amending\n# s, squash = use commit, but meld into previous commit\n# f, fixup = like \"squash\", but discard this commit's log message\n# x, exec = run command (the rest of the line) using shell\n# d, drop = remove commit\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每次調用命令時請留意,git有關於你如何執行這些操作的說明。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最常用的命令是"},{"type":"codeinline","content":[{"type":"text","text":"reword"}]},{"type":"text","text":"、 "},{"type":"codeinline","content":[{"type":"text","text":"squash"}]},{"type":"text","text":" 和 "},{"type":"codeinline","content":[{"type":"text","text":"drop"}]},{"type":"text","text":"。(還有"},{"type":"codeinline","content":[{"type":"text","text":"pick"}]},{"type":"text","text":",默認情況下是這些。)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"花點時間想想你看到了什麼,以及我們將用什麼實現我們的兩個目標,等你思考一下。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有計劃了嗎?完美!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在開始進行更改之前,請注意這樣一個事實,提交是從最舊到最新的順序列出的,因此 "},{"type":"codeinline","content":[{"type":"text","text":"git log"}]},{"type":"text","text":" 輸出的方向相反。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我將從簡單的更改開始進行,因此我們先來修改中間這次提交的提交信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"pick 9e06fca Add text to Alice\nreword 062ef13 Add Bob.txt\npick 0b22064 Add more text to Alice\n\n# Rebase df3ad1d..0b22064 onto df3ad1d (3 commands)\n[...]\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在把 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"的兩次改動改爲一次commit提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"顯然,我們要做的是將最後一個提交 "},{"type":"codeinline","content":[{"type":"text","text":"壓縮"}]},{"type":"text","text":" 到第一個中,所以讓我們"},{"type":"codeinline","content":[{"type":"text","text":"pick"}]},{"type":"text","text":"那次提交後,用"},{"type":"codeinline","content":[{"type":"text","text":"squash"}]},{"type":"text","text":"命令更改 "},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"的提交。在我這個例子中hash是 "},{"type":"text","marks":[{"type":"italic"}],"text":"0b22064"},{"type":"text","text":" 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"pick 9e06fca Add text to Alice\nreword 062ef13 Add Bob.txt\nsquash 0b22064 Add more text to Alice\n\n# Rebase df3ad1d..0b22064 onto df3ad1d (3 commands)\n[...]\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結束了嗎?這能滿足我們的要求嗎?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不會的,對吧?文件中的說明告訴我們:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"# s, squash = use commit, but meld into previous commit\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以我們到目前爲止所做的,將會合並第二次Alice提交和Bob提交的更改。這不是我們想要的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"交互式"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"另一個強大的功能就是改變提交的順序。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你仔細閱讀了評論告訴你的內容,你已經知道怎麼做了:簡單地移動行!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"謝天謝地,你使用了你最喜歡的文本編輯器,所以請繼續將第二個Alice commit移到第一個之後。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"pick 9e06fca Add text to Alice\nsquash 0b22064 Add more text to Alice\nreword 062ef13 Add Bob.txt\n\n# Rebase df3ad1d..0b22064 onto df3ad1d (3 commands)\n[...]\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣就可以了,然後關閉編輯器,告訴 "},{"type":"codeinline","content":[{"type":"text","text":"git"}]},{"type":"text","text":" 開始執行命令。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來發生的事情就像一個普通的"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":":從啓動時引用的提交開始,列出的每個提交都將一個接一個地被應用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在沒有發生這樣一種情況,但是當你重新排序實際的代碼改動時,可能會發生,即你在"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"期間遇到衝突。畢竟你們可能混淆了彼此之間的變化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"像平常一樣解決它們就好。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在應用第一次提交後,編輯器將打開,並允許你爲"},{"type":"codeinline","content":[{"type":"text","text":"Alice.txt"}]},{"type":"text","text":"的合併改動添加一條新的提交消息。我已經刪掉了兩個舊提交的文本,換成了\"Add a lot of very important text to Alice\"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關閉編輯器完成提交後,它將再次打開以允許你更改"},{"type":"codeinline","content":[{"type":"text","text":"Add Bob.txt"}]},{"type":"text","text":"的提交信息。這裏我們把“.txt”刪除然後關閉編輯器繼續。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就這樣!你再次改寫了歷史。這一次比"},{"type":"codeinline","content":[{"type":"text","text":"amend"}]},{"type":"text","text":"的改動要大得多!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你再次查看"},{"type":"codeinline","content":[{"type":"text","text":"git log"}]},{"type":"text","text":",你將看到有兩個新提交取代了我們之前的三個提交。現在你已經熟練使用了 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"的操作,並且達到了我們的預期。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"> git log --oneline\n105177b (HEAD -> interactiveRebase) Add Bob\ned78fa1 Add a lot very important text to Alice\ndf3ad1d (origin\/master, origin\/HEAD, master) Add Alice\n800a947 Add Tutorial Text"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"公共歷史,爲什麼你不應該重寫它,萬一要重寫如何保證安全"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如上所述,如果你的工作流程涉及大量小改動的提交,更改分支歷史是非常有用的一部分。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然所有的小改動有助於簡化你的工作,例如,驗證你的測試組件是否通過時,如果不通過,只刪除或修改這些特定的更改。而你在"},{"type":"codeinline","content":[{"type":"text","text":"HelloWorld.java"}]},{"type":"text","text":" 上面做的100個提交可能不是你想和別人分享的東西。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你最想與他們分享的,是一些帶有很好的提交信息的格式良好的更改,告訴你的同事你爲此做了什麼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"只要所有這些小的提交只存在於你的開發環境中,你就完全可以安全地執行"},{"type":"codeinline","content":[{"type":"text","text":"git rebase -i"}]},{"type":"text","text":"並將歷史更改爲你想要的內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當涉及到改變公共歷史時,事情會變得麻煩。這意味着改動任何已經進入遠程倉庫的內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這時改動已經成爲公共的了,而其他人的分支可能是基於那段歷史。你通常是不想改變遠程分支的內容的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通常的建議是“永遠不要重寫公共歷史!”而當我在這裏重複這一點時,我必須承認,在一些情況下,你可能仍然想重寫公共歷史。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一般這種情況,針對的是歷史並不是“真正”公開的。你當然不想在開源項目的主分支上重寫歷史,或者類似於你公司的發佈分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可能想重寫歷史的地方是你剛剛"},{"type":"codeinline","content":[{"type":"text","text":"push"}]},{"type":"text","text":"出來,只是爲了和同事們分享的分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可能正在進行基於主幹的開發,但是希望共享一些甚至還沒有編譯的東西,所以你顯然不希望有意地將其放在主分支上。或者你可能有一個工作流,在其中共享功能分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"特別是功能分支,你希望能經常將它們"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"到當前的主分支上。但正如我們所知 "},{"type":"codeinline","content":[{"type":"text","text":"git rebase"}]},{"type":"text","text":" 會將分支的提交作爲新提交添加到我們要合的主分支上。這其實改寫了歷史。在共享了這個功能分支的情況下,它更是重寫了公共歷史。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那麼,如果我們遵循“永遠不重寫公共歷史”的準則,我們該怎麼辦?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"怎麼做到不"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"我們的分支但是希望它仍然可以將改動合併到我們主分支的末尾呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不使用共享的功能分支?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"誠然,這個答案實際上是一個合理的答案,但你可能仍然無法做到這一點。因此,你唯一能做的就是接受重寫公共歷史並將更改後的歷史“推送”到遠程倉庫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你只是做了一個"},{"type":"codeinline","content":[{"type":"text","text":"git push"}]},{"type":"text","text":",你會被通知不允許這樣做,因爲你的本地分支已經與遠程分支分離了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你需要"},{"type":"codeinline","content":[{"type":"text","text":"強制"}]},{"type":"text","text":"推送更改,並用本地版本覆蓋遠程版本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如我強調的那樣,你現在可能已經準備好嘗試"},{"type":"codeinline","content":[{"type":"text","text":"git push --force"}]},{"type":"text","text":" 。如果你想安全地重寫公共歷史,你真的不應該這麼做!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你最好使用 "},{"type":"codeinline","content":[{"type":"text","text":"--force"}]},{"type":"text","text":" 的一個更謹慎的用法:"},{"type":"codeinline","content":[{"type":"text","text":"--force-with-lease"}]},{"type":"text","text":" !"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"--force-with-lease"}]},{"type":"text","text":"將在 "},{"type":"codeinline","content":[{"type":"text","text":"push"}]},{"type":"text","text":"之前,檢查你本地版本的遠程分支與實際的遠程分支是否匹配。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣你就可以確保,你不會在重寫歷史的時候無意中抹去可能是別人"},{"type":"codeinline","content":[{"type":"text","text":"push"}]},{"type":"text","text":"的任何改動!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/f1\/f1c5f6585e6206ef07ab8d1bf8dee289.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏我給你留下一句箴言:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"除非你真的確定你在做什麼,否則不要重寫公共歷史。如果你非得這樣做,就要保證安全和強制"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"閱讀歷史"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"瞭解了你的 "},{"type":"text","marks":[{"type":"italic"}],"text":"開發環境"},{"type":"text","text":" (尤其是 "},{"type":"text","marks":[{"type":"italic"}],"text":"本地倉庫"},{"type":"text","text":" )中不同區域之間的差異,以及提交和歷史記錄是如何工作的,執行"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"應該不會讓你感到畏懼了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有時事情還是會出問題。在解決衝突時,你可能執行了"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 操作,意外地接受了錯誤的文件版本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可能不是你添加的功能,而是你的同事在文件中添加了一行日誌記錄。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"幸運的是, "},{"type":"codeinline","content":[{"type":"text","text":"git"}]},{"type":"text","text":" 有一個內置的安全功能,稱爲 "},{"type":"text","marks":[{"type":"italic"}],"text":"Reference Logs"},{"type":"text","text":" ,又名 "},{"type":"codeinline","content":[{"type":"text","text":"reflog"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每當在本地倉庫中更新任何引用(如分支的提示)時,就會添加一個引用日誌條目。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以無論什麼時候,在你 "},{"type":"codeinline","content":[{"type":"text","text":"commit"}]},{"type":"text","text":" 改動,"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":" 或以其他方式移動 "},{"type":"codeinline","content":[{"type":"text","text":"HEAD"}]},{"type":"text","text":"時,都會有一個記錄。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本教程看到這裏,你應該已經知道當我們搞亂了一個"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"時,這個方法是如何派上用場的,對吧?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們知道"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"會將分支的"},{"type":"codeinline","content":[{"type":"text","text":"HEAD"}]},{"type":"text","text":" 移動到我們所基於的位置,然後應用我們的更改。交互式 "},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"的工作原理與之類似,但可能會對提交執行某些操作,例如“壓縮”或“重寫”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你沒有在前面提到交互式變基時在分支上練習過,請再次切換回那部分,我們在那裏有很多的練習和說明。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我們看看通過運行 "},{"type":"codeinline","content":[{"type":"text","text":"git reflog"}]},{"type":"text","text":",我們在這個分支上所做的事情。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可能會看到很多輸出,但頂部的前幾行應該與以下內容類似:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"> git reflog\n105177b (HEAD -> interactiveRebase) HEAD@{0}: rebase -i (finish): returning to refs\/heads\/interactiveRebase\n105177b (HEAD -> interactiveRebase) HEAD@{1}: rebase -i (reword): Add Bob\ned78fa1 HEAD@{2}: rebase -i (squash): Add a lot very important text to Alice\n9e06fca HEAD@{3}: rebase -i (start): checkout HEAD~3\n0b22064 HEAD@{4}: commit: Add more text to Alice\n062ef13 HEAD@{5}: commit: Add Bob.txt\n9e06fca HEAD@{6}: commit: Add text to Alice\ndf3ad1d (origin\/master, origin\/HEAD, master) HEAD@{7}: checkout: moving from master to interactiveRebase\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"情況正是如此,這裏有我們所做的每一件事,從切換分支到"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看到我們所做的事情很酷,但是如果我們在某個地方搞砸了,如果不是因爲每行開頭的hash值,那就沒辦法了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果將"},{"type":"codeinline","content":[{"type":"text","text":"reflog"}]},{"type":"text","text":"與上一次查看"},{"type":"codeinline","content":[{"type":"text","text":"log"}]},{"type":"text","text":" 時的輸出進行比較,就會發現這些節點就是提交時引用的,我們可以像之前那樣去調用它們。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但假設我們實際上不想使用"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"。我們要如何刪除這次所做的改變呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以將 "},{"type":"codeinline","content":[{"type":"text","text":"HEAD"}]},{"type":"text","text":" 移到"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"之前的點,執行"},{"type":"codeinline","content":[{"type":"text","text":"git reset 0b22064"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個例子中, "},{"type":"codeinline","content":[{"type":"text","text":"0b22064"}]},{"type":"text","text":" 是"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"之前的提交。通常,你也可以通過"},{"type":"codeinline","content":[{"type":"text","text":"HEAD@{4}"}]},{"type":"text","text":"取“HEAD四次前”的提交。請注意,如果你在這兩者之間切換了分支,或者執行了創建日誌項的任何其他操作,則可能會有一個更大的數字。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果現在查看 "},{"type":"codeinline","content":[{"type":"text","text":"log"}]},{"type":"text","text":",你將看到三個提交前的原始狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但這也許並不是我們想要的。"},{"type":"codeinline","content":[{"type":"text","text":"rebase"}]},{"type":"text","text":"很好,我們只是不喜歡這種更改Bob commit信息的方式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那麼我們可以在當前狀態下再執行一次"},{"type":"codeinline","content":[{"type":"text","text":"rebase -i"}]},{"type":"text","text":",就像我們一開始那樣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"或使用"},{"type":"codeinline","content":[{"type":"text","text":"reflog"}]},{"type":"text","text":"重新跳回rebase之後並從那裏“修改”提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在你已經知道怎麼做了,自己來試試吧。除此之外,你還知道,有一個"},{"type":"codeinline","content":[{"type":"text","text":"reflog"}]},{"type":"text","text":"命令,它允許你撤銷大多數錯誤的改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"頭圖:Unsplash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:劉詩琴"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:https:\/\/mp.weixin.qq.com\/s\/Kxlipuppuzcb9qKx8ZE_sQ"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:交互式教程!帶你深入理解 Git 原理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"來源:微醫大前端技術 - 微信公衆號 [ID:wed_fed]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"轉載:著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章