【工作目錄 (working directory; working tree)】→ git add → 【索引】→ git commit → 【物件儲存區 (object storage) 】
- 工作目錄 : 你在用的、正準備開發的。通常於此操作指令參數。
- 索引 : 更新索引狀態 ( git status )才能提交 ( git commit ) 新版本。
- 用 git init 建立儲存庫,版本庫。版本庫分為本地、共用、遠端。
👉 做一個小功能就要建立版本,才容易之後追蹤變更,便於修改 bug。
👉 保持、或藉由修改版本紀錄(不要改已分享的),讓版本演進有邏輯性。
檔案狀態
- untracked
- unmodified (未修改的 ) : 第一次加入,或與 HEAD 內容一致的。
- modified (已修改的)
- staged : 等待被 commit 的,下次執行 git commit 就會送入版本庫。
或可分為:
- 加入索引
- 未加入索引
- 新增
- 修改
- 刪除
分支
【遠端儲存庫】 ← push ← / → pull → 【本地】 ← merge ← 【本地分支】
可分為:
- 遠端追蹤分支 : 位於遠端,用來追蹤分支的變化情形。通常無法存取。
- 本地追蹤分支 : 執行 git clone 複製遠端容器回來後,所有遠端追蹤分支會被下載回來,並建立相對應的同名本地追蹤分支。 ( 執行 git branch -a 可見所有本地分支與本地追蹤分支。)
- 本地分支(主題分支 (Topic Branch) 或開發分支 (Development Branch)) : 執行 git branch 時所顯示的分支。存在於本地端。
- 遠端分支 : 遠端儲存庫中的分支。(可以使用 git ls-remote 或 git ls-remote origin 列出所有遠端分支。)
雖然說「概念上」可以分為這四類,但其實這些分支就只是跟隨名稱而已,而這裡的「追踪分支」主要就是用來跟終端的分支做對應的,你不應該直接在這些分支上建立版本(雖然你還是可以現場,但強烈不建議亂搞),而是把這些「本地追踪分支」視為一種「唯讀」的分支。
參照名稱(ref)
- 是相對於絕對名稱的好記名稱。比如HEAD或標籤名稱(清量標籤)都是參照名稱。通常用於「本地分支」、「遠端分支」與「標籤」等情境下。
- 分為一般參照與絕對參照。
所有在 .git\refs\ 下的檔案都是個「參考名稱」
符號參照名稱 (symref)
- 【符號參照】 → 【參照名稱】 → 【絕對名稱】
- 「絕對名稱」是將內容以 SHA1 雜湊運算後的一個 40 字元的字串,你可以用前 4 ~ 40 個字元來當成該 commit 物件的識別名稱。
符號參照比如:
- HEAD : 「工作目錄」中所設定的「分支」當中的「最新版」
- ORIG_HEAD : HEAD 這個 commit 物件的「前一版」,經常用來復原上一次的版本變更。
- FETCH_HEAD : 記錄著遠端儲存庫中每個分支的 HEAD (最新版) 的「絕對名稱」。
- MERGE_HEAD : 「合併來源」的 commit 物件絕對名稱會被記錄在 MERGE_HEAD 這個符號參照中
相對名稱的表示法
- 「~」 : 表示前一版。比如 HEAD~1 或 HEAD~ 代表 HEAD的前一版,f2e~2 或 f2e~~ 代表 f2e 的前兩版。
- 「^」 : 在沒有分支的情況下,如~代表前一版。若有分支,則代表「上一層的第n個parent」。(除了第一個 commit ,都會有一個或一個以上的上一層parent(可能經過合併)。)
圖片來源 : https://f.cloud.github.com/assets/88981/1305052/b7336614-318e-11e3-8b45-78285b0d01ce.png |
暫存版本 stash
是一種特殊的commit,用來在被突然插單時暫存變更紀錄(不然不推薦使用)。儲存 stash 後會將檔案還原至 HEAD。可透過 pop 取回暫存的內容到工作目錄。
(可以建立多個 stash 。)
標籤 tag
分為 :
- 輕量標籤 (lightweight tag) :
是某個 commit 版本的別名 - 標示標籤 (annotated tag) :
- 是 Tag 物件
- 可以包含版本訊息
Logs
只要你透過指令修改了任何參照(ref)的內容,或是變更任何分支的 HEAD 參照內容,就會建立歷史紀錄。
- git log : 顯示版本記錄 ( commit 的記錄 )
- git reflog : 顯示完整的變更歷史的記錄
記錄只是 commit 物件的指標,所以即使被竄改、刪除,都不會影響到目前物件儲存庫的任何內容,也不會影響版本控管的任何資訊。
註:這些版本日誌預設並不會被同步到「遠端儲存庫」,以免多人開發時大家互相影響,所以版本日誌算是比較個人的東西。
歷史紀錄保存期限,預設為90天,若分支已被刪除,無法透過 git log 取得該版本,則為30天。 可自行修改二者期限,比如 "never"。也可針對特定分支進行設定。
整合分支
合併 merge
- 實際上是將另一個分支合併回目前分支,再手動移除另一個分支(如果你還會在分支繼續開發,那就留著)。
- ❗ 合併的動作必須發生在同一個儲存庫中。
- 若是要合併的兩個分支針對相同檔案的同一行都做出修改,則需要使用者自行解決衝突,衝突的檔案會被標示為 unmerged (在合併衝突後可透過 git status 查看此狀態)。
- 如果要合併過來的分支是本分支的後繼,則Git 會直接把本分支指標向前移動指向那個分支的最後,此方式稱為快轉機制(Fast-forward)。若不希望如此,可以使用git merge branchName --no-ff 而非git mrege branchName 藉此更方便找到分支開始與結束的位置;如果要合併過來的分支不是本分支的後繼,則 Git 會找到兩分支最近的共同祖先,生成新的快照並提交。
變基 rebase
比如有A、B兩分支,而你想將B分支變基到A上面,可以在B分支使用 git rebase A ,將B分支上所有修改移到A分支,將與A分支不同的部分,複製產生出新的快照,接到A分支後面(?)。此時A分支的指標並未改變,仍然在它原本只向的A分支的最新版本。需要在A分支合併B分支,才會將其指向變基後的最新版本。
此方式與rebase不同,會變更記錄,為破壞性的操作,無法看見分支的起始與合併點。但它可以讓記錄為線性的,也不會留下太多條路線的記錄,讓整體看起來比較整潔。適合用在要向主項目提交修改之前,將本地端更新了功能的分支變基到 origin/master再提交,讓項目維護者不需要再進行整合工作,只需要快進(Fast-forward)合併即可。請勿用在已經提交的。
其他 git rebase 指令能做的事
- 調換 commit 的順序
- 修改 commit 的訊息
- 插入一個 commit
- 編輯一個 commit
- 拆解一個 commit
- 壓縮一個 commit,且保留訊息紀錄
- 壓縮一個 commit,但丟棄版本紀錄
- 刪除一個 commit
忽略清單 .gitignore 檔案
紀錄不需要加入版控的檔案(記錄檔名或路徑),但僅限於 Untracked file。
還原 revert
其實是透過「新增一個版本」的方式把變更的內容改回來,而且透過這種方式,你可以透過版本歷史紀錄中明確找出你到底是針對哪幾個版本進行還原的。
舉例 : 比如某版本是將檔案內容從「1」改成「2」,則 revert 此版本,會得到將檔案內容從「2」改成「1」的新版本。記得,要能從「2」改成「1」,則需要先有「2」,若沒有則會發生 merge 衝突。
資料來源
- https://github.com/doggy8088/Learn-Git-in-30-days/blob/master/zh-tw/README.md
- https://nulab.com/zh-tw/learn/software-development/git-tutorial/git-collaboration/integrating-branches/
- https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%9A%84%E6%96%B0%E5%BB%BA%E4%B8%8E%E5%90%88%E5%B9%B6
0 comments:
張貼留言