關於 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 | 運行垃圾回收器並確保所有未提交的變更從本地內存中移除 |