4 minutes
為你自己學Git-讀書心得-part1
前言
上班之餘,抽空翻完作者在 2020 年年初因慶祝某件事情,提供的免費電子書 為你自己學 Git
,有件事情必須先說清楚,這本書大部分章節都有放在 宣傳頁 免費觀看,早在前幾年我就有翻這本書的想法,但每次翻了幾頁後又放棄,直到上班一段時間後才吃透這本書,原因是內容生澀難懂,難懂的部分是以前對於書中舉例要解決的狀況不了解,生澀的部分是連指令的用法都不懂,卻介紹指令的背後在做什麼,現在可以吃透自然是有一段時間的使用經驗,遇到過各種狀況,才能披荊斬棘看完。
從我的狀況來評價這本書的幾項要點
-
舉例出符合業界常遇到的狀況,並以此為出發點講解如何解決
-
解釋指令背後,git 做了哪些事,git 如何做到
總結起來就是,不推薦新手入門看這本書,因新手很大一部分需要的不是如何解決問題及了解原理,而是現在要做什麼
早期我覺得最有幫助的是很常見的
內容概要
這裡並不是全部的 git 指令,只是作為閱讀記錄,說明什麼情況適合使用什麼指令
安裝好之後,使用版本指令檢查
$ git --version
設定本機全域的 git 作者,建議和 GitHub 同步一樣的名稱及信箱,不要亂打,之後都會看到
$ git config --global user.name "username"
$ git config --global user.email "username@email.com"
完成後可用指令檢視,這個指令會列出 /User
根目錄中的 .gitconfig
的內容,裡面不只有名稱及信箱,平常不要亂動,特殊情況才會需要手動來調設定
$ git config --list
若有需要在個別專案中設定不同作者,在該專案中設定 local user,注意要先初始化 git init
$ git config --local user.name "local username"
$ git config --local user.email "local.username@email.com"
使用 alias
別名 減少打字字數
$ git config --global alias.co checkout # git co
$ git config --global alias.br branch # git br
$ git config --global alias.st status # git st
$ git config --global alias.l "log --oneline --graph" # git l
$ git config --global alias.ls 'log --graph --pretty=format:"%h <%an> %ar %s"' # git ls
隱藏功能,讓 Git 紀錄檔案衝突(Conflict)時的解決方法,下次再遇到會自動解決,主要用途有二,其一是讓大型專案的紀錄相對乾淨,其二是一種常見的使用場景,合併進測試分支時,第一次解決衝突後,若分支測試失敗後退版,待到下次在合併時不需再處理已發生過的衝突
$ git config --global rerere.enabled true
修改預設編輯器
$ git config --global core.editor emacs # 編輯器改為 emacs,好像沒比較好
# 編輯器改為 VSCode,使用絕對位置或 code 已加入環境變數就可以簡短的寫
# --wait 參數,作用是可以任意編輯存檔,直到關閉編輯分頁才回傳內容給 git,內容裡使用井字號註解有效,但那有什麼意義?
$ git config --global core.editor "'C:\Program Files\Microsoft VS Code\code.exe' --wait"
$ git config --global core.editor "code --wait"
vim 簡易操作說明,分 Normal Mode 及 Insert Mode
在 Normal Mode 時,無法直接修改,但可以 Copy、Paste、Save,要注意的一點是,Paste 之後會切換成 Insert Mode
一般有三個按鍵可以從 Normal Mode 切換到 Insert Mode
i
(insert,當前位置切換)a
(append,切換到當前位置下一格)o
(new line,切換到當前位置下一行)
從 Insert Mode 切換到 Normal Mode 就簡單多了,ESC
切換即可
存檔及離開 Vim 介面的指令必須在 Normal Mode 使用,:w
(存檔)、:q
(離開)、:wq
(存檔並離開),如果修改後不想存檔就離開,用:q
會被擋住,此時使用:q!
(強制離開)
MacOS 根目錄下的 /tmp
,重開機時都會清空,適合用來練習一些東西,看需求使用
$ git add . # 當前位置為出發點,以下的所有更動加入暫存
$ git add --all # 專案根目錄為出發點,整個專案的所有更動加入暫存
個人習慣,專案的第一個 Commit 給一個無內容的空節點,提供 -m
參數就不會進到 vim 介面編輯 commit 內容了
$ git commit --allow-empty -m "git init"
簡化一般先 add 再 commit 的流程,對 Untracked file(通常是新增的檔案) 無效
$ git commit -a -m "update content"
查詢紀錄指令,以往都用 GUI,紀錄一下,雖然以後應該也沒什麼機會用
$ git log
$ git log --oneline --graph # 拉出地鐵線
$ git log --oneline --author="userA" # 搜尋一位特定作者的 commit
$ git log --oneline --author="userA\|userB" # 搜尋多位特定作者的 commit
$ git log --oneline --grep="WTF" # 搜尋 commit 內容包含指定訊息的 commit
$ git log --oneline -S "FormData" # 搜尋 commit 修改內容包含指定修改的 commit
$ git log --oneline --since="5pm" --until="8pm" # 搜尋 指定時間內的 commit,注意台灣時區是標準時間加八小時,前面範例的下午五點到八點等於台灣時間的早上九點到十二點
$ git log --oneline --since="9am" --until="12am" --after="2017-01" # 搜尋 2017年1月之後 指定時間內 的 commit
$ git log --oneline --first-parent # 只顯示 current branch
對特定檔案查詢
$ git log sample.txt # 搜尋指定檔案相關的 commit
$ git log -p sample.txt # 搜尋指定檔案相關的 commit,並且顯示該 commit 修改了什麼
$ git blame sample.txt # 列出指定檔案每一行的 commit 作者、SHA-1 值、日期時間
$ git blame -L 2,4 sample.txt # 功用同上,但指定顯示二到四行
目錄操作,使 git 紀錄追蹤改變,刪除及替換
- 刪除
# 1-1 手動刪除(檔案被刪除)
$ rm sample.txt
$ git add sample.txt
$ git commit -m "remove sample.txt"
# 1-2 git 代刪(檔案被刪除)
$ git rm sample.txt
$ git commit -m "git remove sample.txt"
# 1-3 git 軟刪(檔案未刪除,但在 git 紀錄中標示已刪)
$ git rm sample.txt --cached
$ git commit -m "soft remove sample.txt"
- 更名
# 2-1 手動
$ mv sample.txt case.txt
$ git add --all
$ git commit -m "rename sample.txt to case.txt"
# 2-2 git 代理
$ git mv sample.txt case.txt
$ git commit -m "git rename sample.txt to case.txt"
修改 commit 內容,使用 --amend
參數,只能修改最後一次,注意此方法會產生新的 SHA-1 值,代表是新的 commit,而不是修改原本的 commit
# before
$ git log --oneline
4879515 WTF
7dbc437 add hello.html
abb4f43 update index page
cef6e40 create index page
cc797cd init commit
# use --amend
$ git commit --amend -m "hotfix God bless you"
# after
$ git log --oneline
614a90c hotfix God bless you
7dbc437 add hello.html
abb4f43 update index page
cef6e40 create index page
cc797cd init commit
使用 --amend
參數時,如果有修改放在暫存區,會一起被合進新的 commit 裡,可搭配 --no-edit
參數,效果是不改訊息直接 commit,適用在漏合或短時間內修改,但千萬不要用在已推到 remote 的修改
因 git 版控主要針對檔案的內容
,所以空的資料夾不能直接加入版控,慣例
的作法是在資料夾裡新增 .keep
或 .gitkeep
檔案
.gitignore
,忽略特定檔案,各語言基礎忽略範例
sample.html # 忽略所有檔名為 sample.html 的檔案
*.tmp # 忽略所有附檔名是 .tmp 的檔案
/db/*.sqlite3 # 忽略所有 db ⽬錄下附檔名是 .sqlite3 的檔案
注意一點,如果忽略的檔案在建立 .gitignore
之前就存在版控裡的話,要使用 git rm --cached
,否則會不如預期
有點危險的操作
$ git add -f sample.html # 強制通關,忽略你的忽略
$ git clean -fX # 大寫 X,將所有被指定忽略的檔案強制刪除
$ git clean -fx # 小寫 x,將所有不被追蹤的檔案強制刪除
$ git clean -nx # 小寫 x,列出所有不被追蹤、預計被刪除的檔案
反悔操作
$ git checkout sample.html # 將指定檔案復原到未修改前,可清除修改和回復刪除狀態
$ git checkout . # 將所有修改復原 commit 的狀態,包含修改和刪除狀態
$ git checkout HEAD~2 . # 將所有修改回復到兩個 commit 前的狀態
$ git reset HEAD^ # 回到上一個 commit
$ git reset HEAD^^ # 回到上兩個 commit
$ git reset HEAD~2 # 回到上兩個 commit
$ git reset @~2 # @ 符號是 HEAD 的 Alias
$ git reset 85e7e30 # 回到指定的 commit,但要合理
$ git reset 85e7e30^ # 回到指定 commit 的上一個 commit
$ git revert HEAD^ --no-edit # 還原上一個 commit,此方法會建立新的 commit 宣告,多人合作時,較為禮貌的做法
其中 git reset
指令有三種模式,反悔過程為 A 點到 B 點中間的所有修改
--mixed
預設,反悔過程中的修改會回到工作目錄區-soft
反悔過程中的修改會回到暫存區--hard
反悔過程中的修改全部刪除 強制刪除若要再反悔,使用git reflog
/git log -g
指令檢視HEAD
移動紀錄,看 Commit 的訊息找到想要的版本 SHA-1 值,再使用git reset 版本SHA-1 --hard
指令回復,注意紀錄內容預設只保留三十天 另外有個冷知識,HEAD^^
和HEAD~2
有微妙的不同,HEAD~2
只能指向 current branch 的 current commit 的往前第二個 commit,而HEAD^^
其實是省略寫法,完整版是HEAD^1^1
,如果 current commit 是一個 merge 的節點,使用HEAD^2^1
會移動到被合併分支的倒數第二個節點,如果 merge 節點合了五個分支,則指向最後一個被合的分支就是HEAD^5
,基本上用 GUI 時,完全不需要這種冷知識啦
將個別檔案的指定修改放入暫存
$ git add -p sample.html
# 輸入後會列出所有修改並詢問接下來的動作
# Stage this hunk [y,n,q,a,d,e,?]?
# 輸入問號並 Enter,解釋每一個指令的用途
# 這裡要用的是 e(edit),進入 Vim 或指定編輯器,刪除不想加入暫存的部分,關閉分頁,暫存區就會放入剛剛剩下的修改