關於 Git 二三事
工具往往需要反覆檢驗
關於目錄
- 關於描述問題
- 關於經典場景 && 解決方案
- 關於一點點小技巧
- 關於小結
- 關於常用指令合集
關於描述問題
一圖勝千言
例子: 選擇正確的撤銷方法
| 想要... | 備註 | 解決方案 | | ------------------------------------------------------------------------- | ------------------------------------------------------ | ----------------------------- | | 捨棄工作目錄中對一個檔案的修改 | 修改的檔案未被暫存或提交 | checkout --[file_name] | | 捨棄工作目錄中所有未儲存的變更 | 檔案已暫存,但未被提交 | reset --hard | | 合併與某個特定提交(但不含)之間的多個提交 | -- | reset [commit] | | 移除所有未儲存的變更,包含未跟蹤的檔案 | 修改的檔案未被提交 | clean -fd | | 移除所有已暫存的變更和在某個提交之前提交的工作,但不移除工作目錄中的新檔案 | --- | reset --hard [commit] | | 移除之前的工作,但完整保留提交歷史記錄( “前進式回滾” ) | 分支已經被髮布,工作目錄是乾淨的 | revert [commit] | | 從分支歷史記錄中移除一個單獨的提交 | 修改的檔案已經被提交,工作目錄是乾淨的,分支尚未進行釋出 | rebase --interactive [commit] | | 保留之前的工作,但與另一提交合並 | 選擇 squash(壓縮)選項 | rebase --interactive [commit] |
通過清晰區分自己當前所要的場景並頻繁使用 git status
檢視當前狀態,來明辨的場景
關於經典場景 && 解決方案
Q:檔案刪除造成的變基衝突
```bash First, rewinding head to replay your work on top of it... Applying: CH10: Stub file added with notes copied from video recording lessons. Using index info to reconstruct a base tree... A ch10.asciidoc Falling back to patching base and 3-way merge... CONFLICT (modify/delete): ch10.asciidoc deleted in HEAD and modified in CH10: Stub file added with notes copied from video recording lessons.. Version CH10: Stub file added with notes copied from video recording lessons. of ch10.asciidoc left in tree. Failed to merge in the changes. Patch failed at 0001 CH10: Stub file added with notes copied from video recording lessons. The copy of the patch that failed is found in: /Users/emmajane/Git/1234000002182/.git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue". If you prefer to skip this patch, run "git rebase --skip" instead. To check out the original branch and stop rebasing, run "git rebase --abort". ```
關鍵訊息
When you have resolved this problem, run "git rebase --continue".
此資訊告訴我需要按以下步驟操作
- 解決合併衝突
vim [file_name]
- 當合並衝突已經被解決,執行命令
git rebase --continue
- 檢視當前狀態
git status
- 根據訊息
git reset HEAD [file_name]
- 檢視狀態
git status
- 新增儲存
git add [file_name]
- 新增提交
git commit -m [message]
Q:單個檔案合併並衝突造成的變基衝突
```bash Applying: CH10: Stub file added with notes copied from video recording lessons. Applying: TOC: Adding Chapter 10 to the book build. Using index info to reconstruct a base tree... M book.asciidoc Falling back to patching base and 3-way merge... Auto-merging book.asciidoc CONFLICT (content): Merge conflict in book.asciidoc Recorded preimage for 'book.asciidoc' Failed to merge in the changes. Patch failed at 0002 TOC: Adding Chapter 10 to the book build. The copy of the patch that failed is found in: /Users/emmajane/Git/1234000002182/.git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue". If you prefer to skip this patch, run "git rebase --skip" instead. To check out the original branch and stop rebasing, run "git rebase --abort". ```
解決思路
- 檢視 git 狀態訊息
git status
- 通過 vscode 解決衝突
- 檢視 git 狀態訊息
git status
Q:定位丟失的工作
臨時修改
```bash
檢視 log 與 relog 的區別
檢視壓縮過的專案歷史
git log --oneline
檢視本地操作記錄
git relog
簽出特定提交,這時候會處於分離狀態
git checkout [commit]
遵循 git 提示
git checkout -b [restoring_old_commit]
修改完相關工作後, 合併回分支
git checkout [working_branch] git merge [restoring_old_commit]
刪除臨時分支
git branch --delete [restoring_old_commit]
如果已經發布,需要刪除遠端分支
git push --delete [restoring_old_commit] ```
複製提交 cherry-pick
```bash
檢視圖形化日誌
git log --online --graph
複製另一個分支的提交 在提交資訊的末尾追加一行(cherry picked from commit ...),方便以後查到這個提交是如何產生的。
git cherry-pick -x [commit]
複製一段提交,不包含 start_commit
git cherry-pick [start_commit]..[end_commit]
複製一段提交,包含 start_commit
git cherry-pick [start_commit]^..[end_commit] ```
Q:誤刪除檔案
```bash
通過 HEAD 的快捷方式
git reset HEAD [file_name]
通過 checkout 恢復被刪除檔案
git checout -- [file_name]
合併指令
git reset --hard HEAD -- [file_name]
批量操作
git reset --hard HEAD ```
Q:撤銷分支合併
理想情況下,合併分支後,立馬意識到這是個錯誤合併。Git 在執行合併時候會儲存一個指向最新提交的指標 ORIG_HEADs
,這時候直接通過 reset 取消合併即可
bash
git reset --merge ORIG_HEAD
若沒有意識到這是個錯誤合併,已經繼續提交了,那麼可以開始頭腦風暴了
```bash
穩健的建立一個分支
git checkout -b [pre_branch]
擷取希望儲存的 commit
git cherry-pick commit_to_restore
回到錯誤分支
git checkout [error_branch]
回退
git reset [last_correct_commit]
再次合併
git merge [good_commits] ```
關於一點點小技巧
```bash
stash 進行儲存, 該命令只會儲存已知的檔案進度
git stash save
為加入未跟蹤檔案,可新增 --include-untracked
git stash save --include-untracked
亦可以丟棄它們
git stash save git clean -D
檢視儲存的 stash
git stash list
檢視 stash 中的內容
git show [email protected]{0}
可以通過新增內容來區分 stash
git stash save --include-untracked "msg"
可以繼續工作
git stash list git stash apply [email protected]{0}
刪除 stash
git stash drop [email protected]{0}
應用後刪除 stash
git stash pop [email protected]{0} ```
關於小結
本文是關於《Git 團隊協作》的閱讀筆記,該書已經過於久遠,很多指令也已經更新,例如 git checkout [branch]
已經可以使用 git switch [branch]
來替代了,閱讀之後還是能比較清晰的
關於常用指令合集
| 命令 | 用途 | | --------------------------------------------------------------------- | ------------------------------------------------------------- | | git clone [url] | 下載遠端倉庫 | | git init | 初始化倉庫 | | git status | 獲取 git 狀態 | | git add --all OR git add . | 將所有修改過的檔案和新檔案新增至倉庫的暫存區 | | git commit -m '[message]' | 將所有暫存的檔案提交至倉庫 | | git log | 檢視專案歷史 | | git log --oneline | 檢視壓縮過的專案歷史 | | git branch --list | 列出所有本地分支 | | git branch --all | 列出本地和遠端分支 | | git branch --remotes | 列出所有遠端分支 | | git checkout --track [branch_name] | 建立遠端分支的副本,在本地使用 | | git checkout [branch_name] | 切換到另一個本地分支 | | git checkout -b [branch_name] [branch_name_parent] | 從指定分支建立一個新分支 | | git add [file_name] | 僅暫存並準備提交指定檔案 | | git add --patch [file_name] | 僅暫存並準備提交部分檔案 | | git add HEAD [file_name] | 從暫存區移除提出的檔案修改 | | git commit --amend | 使用當前暫存的修改更新之前的提交,並提供一個新的提交訊息 | | git show commit | 輸出某個提交的詳細資訊 | | git tag tag commit | 為某個提交物件打上標籤 | | git tag | 列出所有標籤 | | git show tag | 輸出所有帶標籤提交的詳細資訊 | | git remote add [remote_name] [url] | 建立一個指向遠端倉庫的引用 | | git push | 將當前分支上的修改上傳至遠端倉庫 | | git remote --verbose | 列出所有可用遠端連線中 fetch 和 push 命令使用的 URL | | git push --set-upstream [remote_name] [branch_local] [branch_remote] | 將本地分支的副本推送至遠端伺服器 | | git merge [branch] | 將當前儲存在另一分支的提交併入當前分支 | | git push --delete [remote_name] [branch_remote] | 在遠端伺服器中移除指定名稱的分支 | | git checkout -b [branch_name] | 建立一個名為 branch 的分支 | | git add [file_name] | 暫存檔案,準備提交至倉庫 | | git commit | 將暫存的變更儲存至倉庫 | | git checkout [branch] | 切換到指定分支 | | git merge [branch] | 將 branch 中的提交併入當前分支 | | git branch --delete | 移除本地分支 | | git branch -D | 移除不包含併入其他分支的提交的本地分支 | | git clone [URL] | 下載一份遠端倉庫的副本 | | git log | 檢視專案歷史記錄 | | git reflog | 檢視分支的詳細歷史記錄 | | git checkout [commit] | 切換到另一個本地分支 | | git cherry-pick [commit] | 將提交從一個分支複製到另一個分支 | | git reset --merge ORIG_HEAD | 移除當前分支中所有在最近一次合併中引入的提交 | | git checkout HEAD [file_name] | 還原已變更但尚未提交的檔案 | | git reset HEAD [file_name] | 從暫存區移除提出的檔案修改 | | git reset --hard HEAD | 將所有已變更的檔案還原到之前儲存的狀態 | | git reset [commit] | 取消暫存在這個提交之前的所有提交中的變更 | | git rebase --interactive [commit] | 編輯,或壓縮提交後的所有提交 | | git rebase --continue | 在解決合併衝突後,繼續變基過程 | | git revert [commit] | 取消應用指定提交中的變更,建立一個共享友好的歷史記錄還原 | | git log --oneline --graph | 顯示分支的圖形化歷史記錄 | | git revert --mainline 1 [commit] | 反轉一個合併提交 | | git branch --contains [commit] | 列出所有包含指定提交物件的分支 | | git revert --no-commit [last_commit_to_keep..newest_commit_to_reject] | 使用一個提交反轉一組提交,而不是為每個撤銷的提交都建立一個物件 | | git filter-branch | 從倉庫中永久移除檔案 | | git reflog expire | 忽略詳細歷史記錄,僅使用儲存的提交訊息 | | git gc --prune=now | 執行垃圾回收器並確保所有未提交的變更從本地記憶體中移除 |