Git 的 100 個情境應用

2020-05-28

使用的情境

如同學習 Gulp 的經驗,直接用需求情境的方式學習新工具是最有效率的,因為情境的需求是與自己切身相關的,而非代入生冷的範例。

  1. 創造屬於自己的情境
  2. 跟著情境實際操作
  3. 將技能融入自己的日常作業流程

情境 1 啟用 Git

Git 博大精深卻十分精簡,有關該專案的版本控制一切相關資訊都只關乎於專案下的 .git 資料夾,而要另一個專案開始啟用 Git 的版本控制機制,僅需要輸入下列指令:

cd folder
git init

情境 2 常用的 Git alias 設定 (git config alias)

git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.sts "status -s"
git config --global alias.br branch
git config --global alias.re remote
git config --global alias.di diff

情境 3 Git Status UTF-8 檔案名稱被編碼的調整

git config --global core.quotepath false

情境 4 忽略特定檔案、資料夾 (gitignore)

一旦啟用 git init 後,專案下的任何新增檔案都會被視為 untracked,這個時候可以藉由設定 gitignore 來告訴 git 忽略掉某些特定的檔案,不要管其異動差別,並且不要放置檔案庫中。通常是編譯過程中產生的檔案或者 npm modules 資料夾等。

使用的方式就是在專案目錄下加入一個 .gitignore 檔案,檔案內所羅列的檔案、資料夾路徑、檔案類型就會自動被 git 所排除。

# 忽略所有 txt 副檔名的檔案
*.txt

# 忽略 node_modules 資料夾
mode_modules/

# 忽略目前目錄下的 dir 資料夾,但不忽略子資料夾中的 dir 資料夾
/dir

# 忽略所有 dir 資料夾下的 txt 檔案
/dir/**/*.txt

情境 5 存入暫存區 (staged) 與遞交至檔案庫 (respository)

# 加入暫存區 (staged)
git add .
# 送入檔案庫 (respository)
git commit -m "備註訊息"

情境 6 補充上一個 commit (amend)

echo "new file" > file.txt
git commit --amend "訊息"

情境 7 切換到上一個 commit (checkout)

git checkout head~

但這樣會出現 Head detached 的情形,正確的方式應該是建立分支,並且切換至分支。

情境 8 取回上一個版本的特定檔案 (checkout)

git checkout 9ee1a27 app.js 

情境 9 比對 Head 與 Unstaged 差異 (diff)

git diff

情境 10 比對 Head 與 Staged 差異 (diff)

git diff --cached

情境 11 比對 Head 與指定 Commit 差異 (diff)

git diff commitId

情境 12 檢查目前的檔案歷次 commit 的異動情形 (blame)

git blame app.js

情境 13 檢視 Commit 紀錄 - 搜尋關鍵字

git log -S "keyword in comment"

情境 14 檢視 Commit 紀錄 - 最近一筆

git log -1

情境 15 檢視 Commit 紀錄 - 特定日期

git log --since="2020-05-27" --until="2020-05-28"

情境 16 檢視 Commit 紀錄 - 這筆紀錄做了什麼

git show 0ba3a74 --stat

情境 17 檢視 Commit 紀錄 - 自定義顯示 format

git log --pretty="%h - %cr - %s" 
選項 輸出說明
%H 該提交 SHA-1 雜湊值
%h 該提交簡短的 SHA-1 雜湊值
%T 「樹(tree)」物件的 SHA-1 雜湊值
%t 「樹」物件簡短的 SHA-1 雜湊值
%P 親代(parent)提交的 SHA-1 雜湊值
%p 親代提交簡短的 SHA-1 雜湊值
%an 作者名字
%ae 作者電子郵件
%ad 作者日期(依據 --date 選項值而有不同的格式)
%ar 作者日期,相對時間格式。
%cn 提交者名字
%ce 提交者電子郵件
%cd 提交者日期
%cr 提交者日期,相對時間格式。
%s 標題

資料參考

情境 18 比較兩筆 Commit 差異

git diff 0ba3b74 a379a71 

情境 19 移除檔案與重新命名檔案 (rm, mv)

已經加入 staged 的話可以透過 git rm 移除 staged並刪除檔案,如果仍在 untracted 階段直接 rm 即可。

echo "untrackted" > untracked.js
rm untrackted.js
echo "unwnated" > untracked.js
git add .
git rm unwanted.js

情境 20 僅移除 stged 狀態,但保持檔案 (rm --cached)

echo "unwnated" > unwanted.js
git add .
git rm unwanted.js --cached
# unwanted.js is untracked

情境 21 從特定版本延伸開發 (branch)

git checkout 9ee1a27 -b dev-branch
echo dev > dev.txt
git add .
git commit -m "dev-branch new commit"

情境 22 放棄目前的所有異動 (reset)

echo "隔著不回頭看的時間 回憶積雪 疊成冬天" > regret.txt
git add .
# oops, I don't need regret.txt anymore
git reset head --hard

情境 23 移除特定異動,保留部分異動 (reset)

echo "隔著不回頭看的時間 回憶積雪 疊成冬天" > regret.txt
echo "I really need this" > keep.txt
git add .
# oops, I don't need regret.txt anymore, but keep keep.txt
git reset head
# regret.txt and keep.txt is untracked now
rm regret.txt

情境 24 刪除所有未追蹤的檔案 (clean)

echo "unwanted" > unwanted.txt
# unwanted.txt is untracked
git clean -f
# unwanted is removed

情境 25 刪除已追蹤,但被 .gitignore 排除的檔案 (clean)

git clean -fX

情境 26 拆除掉目前 Commit (reset)

git reset head~ --hard

情境 27 復原被拆除掉的 Commit (reset)

git reflog
git reset commitId --hard

情境 28 保存 staged 的檔案,回到正式區修正一些事情 (stash)

git stash

情境 29 保存未 commit 所有檔案,回到正式區修正一些事情 (stash)

保存 staged 及 untracked 的檔案,原理是創造一個 staged commit 及 untracked commit 並且合併為一個 stash branch。

git stash -u

情境 30 取回 Stash 暫存的內容 (stash -u)

取回的方式預設是後進先出(LIFO),原理是將 stash 分支合併回目前的分支。

git stash pop

情境 31 取回 Stash 暫存的內容 (stash pop)

取回的方式預設是後進先出(LIFO)

git pop

情境 32 取回特定 Stash 暫存的內容 (stash pop)

取回的方式預設是後進先出(LIFO)

git stash list
git stash pop "stash@{1}"

情境 33 取回 Stash 但保存在 Stash list (stash apply)

取回的方式預設是後進先出(LIFO)

git stash list
git stash apply "stash@{1}"

情境 34 清除 Stash list (stash clear)

取回的方式預設是後進先出(LIFO)

git stash clear

情境 35 用標籤標註歷次發行版本 (tag)

輕量標籤 (lightweight tag) Commit 的別名用途;標籤和分支的差別在於分支會隨著 Commit 而移動,但標籤只會保持在同一個 Commit 上。

git tag tagName commitId

情境 36 用標籤標註歷次發行版本 (tag -a)

標示標籤 (annotated tag) tag 物件,能夠另外帶有訊息。

git tag tagName commitId

情境 37 列出所有標籤 (tag)

git tag

情境 38 強制 branch 改指向 commit (git branch -f)

git branch -f master commitId

情境 39 合併分支 (merge)

git merge branchName

情境 40 合併分支,但不啟用 fast-forward (merge --no-ff)

git merge branchName --no-ff

情境 41 Git Commit 的符號參照、相對參照及別名

項目 說明
HEAD 指向當前分支的最新 commit
ORIG_HEAD Head Commit 的前一版
@ HEAD 的別名
HEAD~n HEAD 前n代 parent commit
HEAD^n HEAD 有n個 上層 parent commit 時選擇其一

情境 42 解析 Git 參照的絕對參照 Sha-1 值

git rev-parse master
git rev-parse HEAD
git rev-parse @
git rev-parse HEAD^
git rev-parse HEAD~2
git rev-parse ORIG_HEAD

情境 43 reglog 立即 expire (reflog expire)

git reflog expire --all --expire=now
git fsck --unreachable
git gc --prune=now

情境 44 將檔案庫推送至伺服器 (push)

git remote -v
git push

情境 45 複製遠端的檔案庫 (clone)

git clone [url|ssh] folderName

情境 46 多個推送伺服器目標 (remote add)

git remote add abbr [url|ssh]

情境 47 推送至指定伺服器目標 (push)

#git push [remote-name] [branch-anme]
git push origin master

情境 48 強制覆寫遠端伺服器的 Commit History

git push -f

情境 49 確認遠端 (remote show)

git remote show origin

情境 50 同步遠端檔案庫 (pull, fetch)

git pull

情境 51 發送 Pull Requst

情境 52 What is GitHub flow

情境 53 使用 Rebase 的情境 (rebase)

剪下分支,並依照指定的基準貼上分支。

Before Rebase
After Rebase

git rebase [new base commitId]

情境 54 使用 Revert 的情境 (revert)

用一個新的 Commit 的還原某個 Commit 的動作,在共用檔案庫的情境尤其適用,避免造成別人的 Commit History 混亂。

git revert commitId

情境 55 使用 Cherry-pick 的情境 (cherry-pick)

揀選特定的 Commit 並依序新增為新的 Commit。

Before Cherry-pick
In Cherry-pick
After Cherry-pick

git cherry-pick commitId1 commitId2 ...

情境 56 使用 Filter-branch 的情境 (filter-branch)

情境 57 使用 Filter-branch 的情境 (filter-branch)

情境 58 關閉自動轉換 CRLF

git config --global core.autocrlf false

情境 59 解決衝突,使用來對方的資料取代自己的

git checkout --theirs conflict.txt
git add .
git commit -m "fix conflict : accept theirs"

合併發生衝突了 | 那如果不是文字檔的衝突怎麼解?

情境 60 Remote Commits is messy 清空遠端 Commits

使用的原理是先將最後 Commit 另存為其他 Branch,並將原本的 Master Branch 刪除後,重新創造 Master Branch,並且再 push 到 GitHub。

git checkout --orphan latest_branch 
&& git add -A 
&& git commit -am "update" 
&& git branch -D master 
&& git branch -m master 
&& git push -f origin master

如果要處理 Hexo Deploy Git Commits 必須切換到:

GitHub\blog\.deploy_git

情境 61 將目前的 Repo 推到新的 Repo 並且保有 Commit History

git remote set-url --push origin newRepoUrl
git push