Bo2SS

Bo2SS

2 獨自使用Git時的常見場景

本機測試環境:macOS 11

14 | 怎麼刪除不需要的分支?#

git branch -d <BRANCH_NAME>

  • -d--delete
  • 有條件地刪除一個本地分支
    • ❗️條件:當該分支被合併到上游分支(本地分支對應的遠端分支,可設置)或者 HEAD(當前分支)時,才能成功執行刪除

git branch -D <BRANCH_NAME>

  • -D--delete --force
  • 強制刪除一個本地分支
    • 當確定刪除分支沒有風險時,可以使用

PS:

  • 不能刪除當前的分支,如需刪除,可通過 git checkout <BRANCH_NAME> 先切換分支
  • 刪除遠程分支: git push <REMOTE> --delete <BRANCH_NAME>
    • 通過 git fetch -p / --prune 同步分支列表,此時就不會顯示遠程已被刪除的分支了

15 | 怎麼修改最新 commit 的 message?#

輸入 git commit --amend ,彈出文本編輯器,修改新的 commit message,如紅框所示:

image

輸入 :wq 保存並退出後,終端顯示修改結果:

image

再次查看 commit 信息:

image

修改成功!

PS:git commit --amend

  • 本質上是替換上一次提交,不局限於修改 message
  • 一般用於修改未 push 到遠端之前的 commit 操作

16 | 怎麼修改老舊 commit 的 message?#

git rebase -i 可以用來修改前幾次的 commit 信息, -i 為使用交互模式

—— 具體步驟 ——

先使用 git log 查看當前的版本歷史:

image

我們想修改順數第 3 個 commit 的 message,那麼需要基於它的父 commit 來操作。

使用git rebase -i d8796c00719323800976e6c7fcfe6b02627ec6b2 命令,末尾添加父 commit 的 hash 值(如果要對最開始的 commit 進行修改,可使用 git rebase -i --root ) ,彈出編輯界面:

image

commit 的順序倒置了一下;從 Commands 部分可以看到有很多用法。

我們使用 reword / r 命令,保留某次 commit,但修改其 message,如下:

image

:wq 保存退出後,又彈出一個新的編輯界面:

image

修改 commit 的 message,再:wq 保存退出。

image

修改成功,❗️可以看到這裡使用了分離頭指針,修改完成後,還更新了 master 分支的指向,說明 commit 的 hash 值很可能發生了改變。

那麼驗證一下,再次通過 git log 查看版本歷史:

image

可以發現順數第 3 個 commit 的 message 修改成功,前 3 個 commit 的 hash 值都發生了改變,除了第 3 個 commit 的 message 都沒有改變,其他信息其實也都沒有改變,可自行驗證。

⚠️:

  • 一般基於自己的分支,用在還沒有提交到集成分支(團隊)之前,否則一定要慎用,其會對集成分支造成影響。
  • rebase 常用於變基,可關注其和 merge 的相同點和不同點,參考

17 | 怎樣把連續的多個 commit 整理成 1 個?#

同樣使用 git rebase -i

—— 具體步驟 ——

先使用 git log 查看當前的版本歷史:

image

現在想合併上面紅框內的 3 個 commit,減少分支裡的 commit 數。

使用 git rebase -i --root 命令,末尾添加父 commit 的 hash 值(因為要對最開始的 commit 進行修改,所以使用--root ) ,彈出編輯界面:

image

要合併的 3 個 commit 見上面紅框內,順序與 git log 展示的順序相反。

使用 Commands 中的 squash / s 命令,可以將某個 commit 融合到前一個 commit 中,修改如下:

image

:wq 保存退出後,又彈出一個新的編輯界面:

image

添加第 2 行,作為融合 3 個 commit 的 message,保留下面每個 commit 的 message,再:wq 保存退出。

image

整合成功,❗️可以看到這裡使用了分離頭指針,修改完成後,還更新了 master 分支的指向。

git log 也驗證了整合的結果,可以發現 2 個 commit 的 hash 值都發生了改變,因為 commit 的 message 或者父 commit 的指向發生了改變。

PS:

  • 整合後會導致一些 commit 沒有用了,git 會進行清理。
  • 通過 gitk --all 觀察此時的分支情況:

image

  1. 可以發現出現了兩棵樹,兩個分支之間已經沒有關聯
  2. 這是因為 master 分支的根 commit 已經改變

18 | 怎樣把間隔的幾個 commit 整理成 1 個?#

命令: git rebase -i

通過 git log 命令查看版本歷史:

image

想合併如紅框所示的間隔的幾個 commit,同樣使用 git rebase -i 76e5c9ca 命令,後面添加的是父 commit 的 hash 值,彈出如下熟悉的窗口:

image

調整要合併的 commit 位置,並使用 s 命令,修改如下:

image

:wq 保存退出後,提示存在合併衝突,需要解決。

image

上面藍框中提示了接下來可以進行的操作,這裡我們嘗試第一種方式:解決衝突。

PS:還可以借助 git status 查看目前建議的操作:

image

接下來查看 readme 文件,解決裡面的衝突,刪除紅框位置的代碼即可:

image

再運行 git add readme 添加剛才的修改記錄。

然後按前面的提示運行 git rebase --continue 命令,彈出編輯框,輸入 message 信息, :wq 保存退出即可(可能還需要解決衝突,重複上述步驟即可)

最後 git log 查看版本歷史:

image

可以看出:如果被間隔的 commit 和要合併的 commit 有關聯,很可能不符合預期,導致它們被合併成一個 commit,所以自己要對這幾個 commit 的內容非常清楚。

PS:個人認為不太實用,容易產生衝突。

19 | 怎麼比較暫存區和 HEAD 所含文件的差異?#

命令: git diff --cached

別忘了這張圖:

image

  • HEAD 指向的是當前分支,分支指向的則是一個 commit。

演示:

修改 readme.md 文件後,輸入 git add readme.md 將修改添加到暫存區;

再輸入git diff --cached 比較暫存區和 HEAD 的差異:

image

可以看到添加了兩行文本,確認符合預期後就可以 commit 了。

20 | 怎麼比較工作區和暫存區所含文件的差異?#

命令: git diff

還可以在命令後添加文件名,從而比較指定文件在工作區和暫存區的差異,如 git diff readme.md ,當然也可以添加多個文件名。

21 | 如何讓暫存區恢復成和 HEAD 的一樣?#

場景:暫存區的內容不想要了,暫存區👉HEAD。

命令: git reset HEADHEAD 後面什麼也不加,則將所有文件恢復成和 HEAD 一致

可以通過 git status 觀察 reset 前後的變化,見下圖:

image

reset 之後,修改的操作又放到了工作區,可以通過 git add 命令又將它們添加到暫存區。

PS:

git diff --cached 可以驗證暫存區和 HEAD 內容的一致性。

git reset HEADgit restore --staged . 的效果是一樣的,後者是 git 2.23 + 後新增的。

22 | 如何讓工作區的文件恢復為和暫存區一樣?#

場景:工作區做了修改,但是不想要了,想恢復為和暫存區一樣。

命令: git checkout <FILENAME>

再提醒下這張圖:

image

過程演示:

首先通過 git add ,將修改後的 readme.md 文件,從工作區添加到暫存區:

image

觀察操作前後 git diff --cached 的結果,即暫存區與 HEAD 差異的變化,可知 git add 成功。

然後,再來修改readme.md 文件,通過 git diff 觀察工作區和暫存區的差異:

image

紅框部分為此次的修改。

通過 git status 查看工作區和暫存區的情況:

image

圖中上半部分是暫存區中待 commit的內容;下半部分是工作區中待添加到暫存區的內容。

可以看到兩個部分都有對 readme.md 的修改,分別對應剛才的兩次修改。


❗️此時,如果想把 readme.md 文件在工作區的內容恢復回暫存區狀態,使用 git checkout readme.md 即可。

image

可以看到工作區的 readme.md 文件已經不在待添加狀態了。


PS:

  • 慎用git checkout ,可能導致文件找不回。
  • Git 2.23 之後,用 git switchgit restore 來替代 git checkout 功能:git switch 替換 git checkout 切換分支的功能; git restore 替換對工作區文件進行恢復的功能。
  • git checkout <FILENAME>git restore <FILENAME> 的效果是一樣的,後者是 git 2.23 + 後新增的。

23 | 怎樣取消暫存區部分文件的更改?#

命令: git reset HEAD [FILENAME] ,類似第 21 節,在命令後面多添加了具體的文件名,也可以指定多個文件,用空格隔開。

下面示例展示了暫存區中的修改被一個一個退回到工作區中:

image

如果想把工作區中的修改再添加到暫存區,使用 git add 命令即可。

24 | 消除最近的幾次提交#

命令: git reset --hard <HASH_OF_COMMIT> ,可以改變 HEAD 的 commit 指向,並且暫存區和工作區的內容都回到該 commit。

請看下面的例子:

image

觀察 git reset --hard 前後的兩個點:

1)通過 git log 可以看出 HEAD 的指向後退了兩個 commit;

2)通過 git diff 可以看出工作區和暫存區從存在差異到沒有差異。

25 | 看看不同提交的指定文件的差異#

命令: git diff <HASH_OF_COMMIT> <HASH_OF_COMMIT> [-- FILENAME]

最後添加指定的文件,如果不添加,則會展示所有文件的差異;

<HASH_OF_COMMIT> 可以用直接換成分支名,分支名本質上也是指向一個 commit。

PS:加--會使 Git 更明確你的意圖。

26 | 正確刪除文件的方法#

命令: git rm <FILENAME>

效果如下:

image

本質上相當於刪除了文件,並把這個刪除操作同步到了工作區和暫存區裡,等同於:

image

先通過 git reset --hard HEAD 讓工作區和暫存區都恢復到 HEAD 的狀態;

通過 git status ,分別觀察 rm 文件以及 git rm 文件後,工作區和暫存區的狀態:

1)前者改變了工作區,但沒有暫存;

2)後者同步了暫存區,此時可以 commit 這次修改了。

27 | 開發中臨時加塞了緊急任務怎麼處理?#

臨時加塞了緊急任務,當前工作還只是半成品,該怎麼辦呢?

git stash :將當前工作區和暫存區的內容遷移到一個額外的棧上,只對被跟蹤的文件有效。

完成了緊急任務,此時要恢復剛剛的半成品,先查看 stash 了哪些內容。

git stash list :顯示 stash 的記錄列表。

然後,將最近的一次 stash 內容恢復到工作區內。

git stash apply :恢復棧頂的保存記錄,且記錄列表裡還保留該記錄。

git stash pop :恢復棧頂的保存記錄,並把記錄列表裡的該記錄刪除

  • PS:也可以指定某一個記錄恢復。

過程展示:

來了緊急任務,先將暫存區裡未完成的內容 stash 起來。

image

此時 stash 記錄列表裡添加了一個記錄 {0},並且當前工作區和暫存區裡已經乾淨。

忙完了,恢復 stash 裡最近的一個記錄。

image

可以看到 apply 是不會清除 stash 記錄的,並且被恢復的內容放到了工作區,而之前 stash 的是暫存區的內容。

再來另一種方式的恢復,使用 pop 並且添加 --index 參數。

image

可以看到 pop 會清除該 stash 記錄,並且被恢復的內容放到了與 stash 時一樣的暫存區, --index 其實就代表還會恢復暫存區。


PS:

WIP 全稱 Work in progress,表示正在工作過程中,引申含義為 “目前工作區中的代碼正在編寫中,這部分代碼不能獨立運行,是半成品”。

28 | 如何指定不需要 Git 管理的文件?#

方法:在 .gitignore 文件中聲明文件類型或文件名即可(必須是 .gitignore

聲明 doc / 和 doc 的區別演示

1)doc/:忽略文件夾,但不會忽略同名的文件

創建 doc 文件夾,在裡面添加 readhim 文件。

image

.gitignore 文件裡添加 doc/ 後,Git 將忽略對 doc 文件夾的跟蹤。

但是,將 doc 文件夾換成 doc文件後,Git 將不會忽略跟蹤 doc 文件。

image


2)doc:同時忽略文件夾和同名文件

而對於忽略規則 doc,不管是文件夾還是同名文件,都会讓 Git 忽略對其跟蹤。

image


⚠️:

  • 常用通配符 * 忽略同類的文件
  • 文件已經被跟蹤後, .gitignore 文件就不起作用了
    • 如果提交 commit 後,想再忽略一些已經提交的文件呢?
    • 可以把想忽略的文件先添加到 .gitignore 文件中,然後通過 git rm --cached FILENAME 的方式忽略掉無需跟蹤的文件。
  • 在 Github 上新建倉庫時,可以選擇添加一份合適的.gitignore 文件:(很貼心❤️)

image

PS:對於不同的語言或項目,常見的 .gitignore 文件可參考github/gitignore庫。

29 | 如何將 Git 倉庫備份到本地?#

相關命令: git clonegit remotegit push


常用傳輸協議:本地協議、http/https 協議、ssh 協議,後兩者在工作中最常用。

傳輸協議又可以分為兩類:啞協議和智能協議,這裡以本地協議為例:

1)/Path/to/.git;2)file:///Path/to/.git

前者為啞協議,後者為智能協議。


那麼兩者在 Git 備份時有什麼區別呢?

智能協議相比啞協議,1)傳輸進度可見,2)並且傳輸速度更快。


智能協議和啞協議的效果對比:

通過 pwd 獲取到了之前演示用的倉庫地址為: /Users/double/Desktop/test

現在通過兩種協議,將倉庫備份到另外的地方:test_remote 目錄下。

啞協議

image

⚠️: --bare 代表創建裸倉庫,即不帶工作區的倉庫,其方便作為服務端;備份的是.git 文件夾,所以地址要添加 /.git ;最後的 ya.git 表示倉庫名。

智能協議

回到 test.remote 目錄下,使用智能協議,即添加 file:// 前綴。

image

對比可以看到直觀的區別:啞協議不帶進度條,而智能協議有進度條。


上面展示的是從遠端克隆 (clone )倉庫到本地的過程,那如何推送 (push ) 本地倉庫到遠端呢?

回到原倉庫(這裡原倉庫的角色從遠端轉變成了本地),新建一個名為 new 的分支。

image

此時遠端 intel.git 倉庫還只有 3 個分支:

image

在本地添加遠端伺服器:

git remote add intel file:///Users/double/Desktop/test_remote/intel.git

PS: intel 為伺服器別名,後面是伺服器地址,使用智能協議。

image

通過 git remote -v 可以查看詳細的伺服器信息。

接下來進行推送: git push REMOTE_NAME 命令

image

⚠️:直接推送會報錯,需要先設置上游。

再次查看下遠端 intel.git 倉庫的分支情況:

image

可以看到分支 new 已經被推送過來了~

學到這裡,有哪些是你之前不知道的呢?歡迎交流~

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。