Git Cheat Sheet

Git-Cheat-Sheet

SourceTree 快速鍵

SourceTree 是一款提供 GUI 界面來管理 Git 版本控制內容的軟體。

常用快速鍵:

  • Ctrl + 1 切換到 Workspace 下的 File Status 頁面,用於提交變更
  • Ctrl + 2 切換到 Workspace 下的 History 頁面,用於查看分支
  • Ctrl + 3 切換到 Workspace 下的 Search 頁面,用於搜尋提交相關資訊
  • Shift + Ctrl + P Push 推送 Git 提交到遠端
  • Shift + Ctrl + L Pull 取得遠端 Git 提交
  • Shift + Ctrl + F Fetch 遠端 Git 分支資訊

REF: SourceTree Keyboard Shortcuts

只取得最新的 commit

# 複製儲存庫時,取得指定分支且不包含完整的歷史紀錄
git clone -b ${BRANCH_TO_BUILD} --depth 1 --single-branch ${REPO_URL}

Git Log

在終端機中查看 Git Tree 可參考下列指令:

git log --graph --all --oneline --decorate --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'

執行下列指令可建立 alias,直接下 git tree 即可

git config --global alias.tree "log --graph --all --oneline --decorate --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'"

建議搭配 git log -[Length] 參數,只顯示前幾筆紀錄,例如 git tree -20 只顯示前 20 筆紀錄

關於 git log 參數說明,可參考此文件

Pro Git

此為精進 Git 技巧的書籍,有善心人士幫忙翻譯成中文電子版,幾乎所有的用法和技巧裡面都有交代到。

Pro Git in Chinese

gitignore 大全

基本指令

建立 Repository

$ git init
$ git add README
$ git status
$ git commit -m "First Commit"

常用指令

$ git status # 查看發生改動的文件列表
$ gitk # 圖形化工具查看文件改動,Git 自帶的圖形化界面
$ git checkout . # 取消所有修改
$ git checkout xxxFile # 取消某個文件的修改
$ git add -A # 新增所有修改
$ git commit -m 'commit message' # 提交修改

$ git push # 提交程式碼到遠程分支, 預設使用 origin 作為名稱
$ git pull # 從遠程倉庫獲取最新程式碼

$ git fetch # 從遠程獲取 branch/tag 訊息
$ git branch # 查看本地分支, -r 查看遠程分支, -a 查看所有
$ git checkout develop # 切換到 develop 分支, -b 新建並切換到分支
$ git merge develop # 將 develop 分支 merge 到當前分支

$ git tag # 查看 tag
$ git tag -a v1.0 -m 'tag message' # 新增 tag
$ git push --tags # 同時推送 tag 到遠程倉庫

$ git help xxxCmd # 查看幫助文件, 會用瀏覽器打開 html 文件
$ git config --global user.name "User-Name" # Git 設定, --global 全局生效

tag 常用指令

$ git tag # 查看本機 tag
$ git tag TAG_NAME # 新增 tag
$ git tag -a TAG_NAME -m 'tag message' # 新增 tag 同時建立提交訊息
$ git tag -d TAG_NAME # 刪除本機 tag
$ git push -d origin TAG_NAME # 刪除遠端 tag

使用 Stash 暫存功能

$ git stash # 暫存本地修改
$ git stash pop # 恢復暫存的修改

進階指令

檔名大小寫的重新命名

Git 對於檔名的處理是大小寫不分的(case-insensitive) 如果只是把 program.cs 改為 Program.cs,用 git status 會看不到任何改變,請使用下列命令列處理

$ git mv -f program.cs Program.cs

如果是資料夾名稱要做大小寫修改了話,則需要兩個步驟,才能變更成功

$ git mv -f folder temp
$ git mv -f temp FOLDER

修改版控資料夾名稱

使用 renamemove 做資料夾更名

git mv <old name> <new name>

Windows 中檔名過長的問題

在 Windows 上使用 SourceTree 做 Git 版控的時候,當有檔案的儲存路徑超過 4096 字元,就會出現下列錯誤訊息 Filename too long

解決方案,請使用系統管理員權限開啟命令提示字元,接著輸入以下指令:

git config --system core.longpaths true

還原上一(多)個 Commit

基本上有兩種指令可以用 resetrevert

reset 比較強烈一點,會把前面的 Commit 移除,因此如果該 Commit 已經提交到遠端上時,搭配 git push -f 才能強制 Commit 給覆蓋到遠端。

另一種 revert 比較溫和,不會把前面的 Commit 移除,而是會建立一個新的 Commit 來記錄你要還原哪個指定的 Commit 內容,而透過下列指令可以還原前面多個 Commit:

git revert --no-commit HEAD HEAD~1 HEAD~2

上面的指令搭配 --no-commitrevert 指令在還原後不要馬上建立一個新的 Commit 點,並且透過指定 Commit 點來還原,而上面的 HEAD HEAD~1 HEAD~2 則是代表當前、前一個、前前一個 Commit 點。

REF: Git - how to revert multiple recent commits

拋棄所有尚未 Commit 的資料

$ git reset --hard    #to discard changes made to versioned files
$ git clean -xdf      #to erase new (untracked) files, including ignored ones (the x option). d is to also remove untracked directories and f to force.

找尋遺失的 Commit 紀錄

建議只要開發到一定的階段,務必要下一個 Commit 當作記錄,只要 Commit 過 Git 都會有紀錄,即便是”剛剛”被刪掉的!

如果不小心下了 git reset --hard HEAD^,於是上一個 Commit 就會消失了,可以使用 git reflog 指令然觀看開發者全部 git 的操作記錄,裡面詳細記載你曾經下過的 git 指令,然後透過這個紀錄將剛剛的 Commit 救回來。

$ git reflog
794be8b HEAD@{0}: reset: moving to HEAD^
5e2be6f HEAD@{1}: commit (amend): update
bfa593c HEAD@{2}: cherry-pick: update
794be8b HEAD@{3}: reset: moving to 649c658
794be8b HEAD@{4}: reset: moving to HEAD^
649c658 HEAD@{5}: commit: update
794be8b HEAD@{6}: commit (initial): addd

執行 git reflog 可以看到類似上面的 Commit 的記錄,接著可以透過 git reset --hard xxxxx,或者是用 git cherry-pick xxxxx 將其中一個 Commit ID 記錄抓回來。

取得版控庫中特定資料夾的內容

版控庫的檔案數量很多,但是只想要取得其中的某個資料夾下的檔案時,可以使用 git sparse-checkout 指令。

https://github.com/dotnet/samples/blob/main/core/nativeaot/NativeLibrary/NativeLibrary.csproj

git clone --depth 1 --single-branch -b main --filter=blob:none --sparse https://github.com/dotnet/samples.git
git sparse-checkout set core/nativeaot/NativeLibrary
git clone --depth 1 --single-branch -b main --filter=blob:none --sparse [GIT_URL]
cd [FOLDER]
git sparse-checkout set [SUBFOLDER_PATH]

簽出 PR 程式碼

參考:How can I check out a GitHub pull request?

Pull Request(PR) 不是 Commit 點也不是分支,要將 PR 程式碼簽出至本機,可以透過下列兩種方式:

# 指定遠端的 PR ID,例如 939
$ git pull origin pull/939/head
# 取得遠端 PR 資訊並建立分支,BRANCHNAME 為自訂的分支名稱
$ git fetch origin pull/ID/head:BRANCHNAME
# 再切換到該分支
$ git checkout BRANCHNAME

以上的動作,是會將 PR 的提交抓下來後,將 HEAD 切到該 PR 的提交點,作為當前的工作目錄。

修改提交的 PR 程式碼

通常 PR 的提交者會允許原始專案的維護者編輯該 PR,在 PR 的頁面右下角會看到下面這樣的圖示:

Allow edits from maintainers

如果該選項有打勾,則原始專案的維護者可以透過下面的指令,將修改後的程式碼提交到提交 PR 作者的分支中。

git push git@github.com:[USER/REPO] [LOCAL_BRANCH_NAME]:[REMOTE_BRANCH_NAME]

  • [USER/REPO] 提交 PR 的作者及專案名稱
  • [LOCAL_BRANCH_NAME] 本機要提交的分支名稱
  • [REMOTE_BRANCH_NAME] 遠端要接受提交的分支名稱

REF: Adding commits to another person’s pull request on GitHub

刪除遠端和本地端的分支

http://stackoverflow.com/questions/2003505/delete-a-git-branch-both-locally-and-remotely As of Git v1.7.0, you can delete a remote branch using

$ git push origin --delete <branchName>

刪除遠端和本地端的 Tag

# 刪除本地端的 Tag
git tag -d TagName
# 刪除遠端的 Tag
git push origin :refs/tags/TagName
# 刪除本地端的 Tag 然後使用推送來刪除遠端的 Tag
git tag -d TagName
git push --delete origin TagName

更新成符合 .gitignore 設定的追蹤狀態

只要檔案有被提交過,就會持續被 Git 所追蹤,因此再建立 .gitignore 之前,就已經提交檔案了話,那麼即使再從 .gitignore 內加入新規則,也無法排除已經被追蹤的檔案。

.gitignore 只能忽略那些沒有被追蹤的檔案 (Untracked Files)。

如果想要使更新後的 .gitignore 設定生效,排除已經被追蹤過的檔案時,可以參考以下步驟:

  1. 清除本機 Git 的快取,相當於將所有檔案移除,但沒有刪除檔案
  2. 重新加入 Git 追縱,這時會套用 .gitignore 設定
  3. 提交,這個提交內容會是將排除的檔案刪除
git rm -r --cached .
git add .
git commit -m 'update .gitignore'

下載 .gitignore 設定檔

建立以下 git alias:

# 必須是 Windows 平台執行以下設定
git config --global alias.ignore '!gi() { curl -sL https://www.gitignore.io/api/$@ ;}; gi'

# 必須是 Linux/macOS 平台執行以下設定
git config --global alias.ignore '!'"gi() { curl -sL https://www.gitignore.io/api/\$@ ;}; gi"

就可以使用以下方式,快速建立 .gitignore 設定檔:

# 取得範本清單
git ignore list
# 下載 Visual Studio 範本
git ignore vs > .gitignore
# 下載 Visual Studio Code 範本
git ignore vscode > .gitignore
# 同時下載 Visual Studio 與 ASP NET Core 範本
git ignore visualstudio,aspnetcore > .gitignore

REF: 如何設定 git ignore 命令並自動下載所需的 .gitignore 範本

透過 https 下載套件,取代 git protocol

現在前端套件幾乎都會透過 Bower 來下載,而 Bower 預設使用 git protocol 來下載原始檔案,如果遇到 timeout 逾時,也就是無法透過 git:// 方式,就必須要切換成 https:// 下載,切換方式很容易,請在 Console 鍵入底下指令:

$ git config --global url."https://".insteadOf git://

移除 Git 歷史紀錄

參考本站文章

移除前次 commit

git reset 可以砍掉 commit 重來,但修改的程式依然存在:

git reset HEAD^

執行上列指令就會回到前一版本,其中 ^ 表示是前一版,可以使用多個 ^ 來回到多前 n 版。

此指令常用於發現前一次 commit 有問題時,可以回到前一次 commit,並於修改後再重新 commit。

將檔案加入上一個 commit

REF: How to add a file to the last commit in git?

如果已經 commit 了,但想將再加入檔案時,可以下列指令

git add THE_FILE_YOU_WANT_TO_ADD
git commit --amend --no-edit

--no-edit 參數允許你修改上一個 commit 的內容,而不修改其 commit 訊息

設定 Git 自訂指令

可以使用 git config alias.CUSTOME CUSTOM_COMMAND 來設定自訂指令,之後執行 git CUSTOME 就可以了

推薦執行下列指令,建立 git ll 顯示簡易的命令列線圖

$ git config --global alias.ll "log --pretty=format:'%h %ad | %s%d [%Cgreen%an%Creset]' --graph --date=short"

git ll

協作專案時常用指令

  • 自訂 push/fetch 不同的來源 _ 透過 git config 設定 _ git config --local remote.origin.url <fetchurl> _ git config --local remote.origin.pushurl <pushurl> _ 透過 git remote 設定 _ git remote set-url origin <fetchurl> _ git remote set-url origin --push <pushurl> _ 查看遠端儲存庫設定 _ git remote -v

Git 內部細節

.git 資料夾

  • .git 資料夾包含整個版控的設定及歷史紀錄 * 這也是完整的儲存庫備份

資料結構

整個 Git 的資料結構主要由四種物件組成

  • 物件(Object) _ 執行 git add, git tag 指令就會產生物件 _ 查看物件的指令 git cat-file -t [SHA-1] _ SHA-1 是使用檔案內容做 HASH 所產生的 _ -t 顯示該物件的類別 _ -s 內容大小 _ -p 顯示內容 _ blob _ 紀錄資料快照,不存檔名 _ tree _ 這裡面會有檔名和 Object 的對照 _ commit _ 裡面的 author 和 committer 可能是不同的 _ 當使用 rebase 的時候,會重新 commit 原作者的內容,這時候 cimmitter 就會是新的人 _ 在 GUI 工具中看到的線圖,就是 commit 物件的資訊 _ tag _ 指向某一個 commit * tag 有兩種樣態,一個是這裡的 Object,另一個是參考的指標,存放在 refs/tags
  • 索引(Index) _ 索引檔內會有所有版控中的檔案,保存要進儲存庫之前的所有檔案狀態 _ 當資料要寫入 Git 的時候,會需要索引檔 * 空的資料夾是無法加入版控的,如果硬要加入版控了話,至少要有一個檔案,建議用 .gitkeep
  • 分支(Branch) _ 記錄在 .git\refs\heads 資料夾下,例如 master _ 內容是一個 SHA-1 的指標,指向一個 commit

重置 GitFlow

Those commands remove all the sections of the git config file related to gitflow.

git config --remove-section "gitflow.path"
git config --remove-section "gitflow.prefix"
git config --remove-section "gitflow.branch"

Then you can re-init gitflow as usual.

git flow init

Git Client Tools

指令視作強大的,但畢竟人是視覺動物,有時候看到畫面(線圖)會感覺比較親切。


參考資料:


Poy Chang

Trial and Error