天天看點

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

還記得我剛開始用git,還沒了解rebase和merge的差別時,就看到隊友童鞋飛一樣地打指令,幾秒鐘把事情搞定了,然後在我還沒看清楚他幹了啥就清理了界面😂(這貨有強迫症)。那時起,我開始意識到漂亮的GUI不一定有打指令快捷友善。

這篇我想分享一些我感覺很好用的方法,包括:

  • git指令 - 建議通過

    git --help

    來檢視更多的細節和選項
  • Oh-my-zsh的快捷指令 - 這裡有完整的Cheatsheet
  • VSCode擴充插件

目錄

    • 開始工作之前
      • 将倉庫克隆到本地
      • 切換到某個分支
      • 建立新分支
      • 分支重命名
      • 檢視分支狀态
      • 保持分支最新
    • 完成并送出修改
      • 送出前驗證一下自己的改動
      • 送出改動
      • 修改送出資訊
      • 把修改推送到遠端
    • 解決沖突
      • 第一選項是rebase
      • Rebase或merge之前考慮先壓縮一下commits
      • 比較複雜的情況下選用merge
      • 解決沖突
    • 為啥代碼寫成這樣
    • 清理不需要的分支
      • 清理遠端的分支記錄
      • 本地分支的清理

開始工作之前

将倉庫克隆到本地

大部分時候隻需要将git網站提供的clone指令複制黏貼就好,或者用指令:

用Oh-my-zsh可以更為簡短:

并且它還包括了一個遞歸clone所有submodule的選項。

不過現在我更喜歡用VSCode的git指令工具來clone,這樣就可以順便打開新clone的倉庫開始工作:

  1. Mac用

    command

    +

    shift

    +

    p

    ,Windows用

    ctrl

    +

    shift

    +

    p

    打開指令面闆,輸入

    git

    來找到

    Git: Clone

    用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作
  2. 粘貼倉庫位址:
    用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作
    如果是github的倉庫可以直接用"Clone from Github"功能(需要github賬号登陸)
  3. 選擇目的位址:
用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作
  1. 克隆完成後,右下角彈窗會提示打開倉庫:
    用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

切換到某個分支

我通常用指令行加

tab

自動完成分支名來切換自己的分支:

git checkout <分支名>
// In Oh-my-zsh
gco <分支名>
           

需要檢視别人分支而我不熟悉分支命名的時候,就用VSCode git擴充在左下角狀态條上放的分支切換入口:

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

點選後會彈出指令行選擇分支:

![VSCode status bar - switch git branch]

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

建立新分支

新分支的建立隻需加上

-b

選項:

git checkout -b <分支名>
// Oh-my-zsh:
gco -b <分支名>
           

分支重命名

有時候我不小心打了錯别字或者有更好的名字,就用以下方式重命名:

git branch -m <新名字>
// Oh-my-zsh:
gb -m <新名字>
           

檢視分支狀态

如果一個分支已經推送到遠端,并且存在有多人協作、或是一個人用多裝置(公司電腦和家裡電腦)寫代碼,那時不時檢視一下現在分支狀态是個不錯的習慣。這樣可以避免因為沒有基于最新代碼開始工作而導緻的一些麻煩。

指令:

git fetch
git status
// Oh-my-zsh:
gf
gst
           

然後就會列印類似這樣的資訊:

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

有時候感覺這資訊太簡單了,不夠清晰。那我就會檢視git曆史。大多數時候隻需要最基本的指令就行了:

git log
           

不過這指令提供了不少有意思的選項(說實話太多了記不住啊),比如

--stat

會顯示變化的檔案,

--graph

會畫個醜醜的分支圖,

--oneline

把每個commit的資訊壓縮成一行顯示……很多都太長了,還是用Oh-my-zsh别名吧,比如:

glg // git log --stat
glgg // git log --graph
glo // git log --oneline --decorate
           

保持分支最新

如果我的分支沒有任何修改,但

git status

告訴我這個分支上有更新:

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

這時隻需要用指令:

git pull
// Oh-my-zsh
gl
           

來更新本地的分支。

如果不巧遠端分支有更新的話,會稍稍麻煩一些。我們會在稍後的"解決沖突"部分作詳細讨論。

完成并送出修改

送出前驗證一下自己的改動

在送出代碼前,我通常會再看一眼自己的改動來降低送出不必要的代碼(比如測試用的console.log)和錯誤的幾率。這時就感到VSCode自帶的git diff非常好使:

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

點選“重新整理”圖示來顯示更新,然後可以點選“樹狀清單”圖示切換為更清晰的目錄,點選其中的檔案會顯示非常容易看清楚改動的比較視窗。

送出改動

驗證完畢後,在這個“SOURCE CONTROL”裡可順便選擇這次需要送出的檔案(點檔案或檔案夾右側的➕号):

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

再輸入适當的送出資訊,點選✅圖示送出。

然而這兒有個比較麻煩的地方是,送出經常會因為配置了commit hook樣式驗證、type類型驗證而失敗,并且失敗後在VSCode OUTPUT面闆列印的錯誤資訊不如直接在指令行運作時列印的好閱讀。是以我更喜歡指令行送出:

git commit -m 'My commit message'
// Oh-my-zsh
gc -m 'My commit message'
           

如果想跳過手動stage檔案,直接送出所有改動,則可以加

-a

選項:

git commit -am 'My commit message'
// Oh-my-zsh
gc -am 'My commit message'
// 或
gcam 'My commit message'
           

注意

-a

選項時不會包括新建立,以前沒有送出過的檔案的。這時候需要多加一步:

// 把所有目前目錄下的檔案都stage:
git add .
// Oh-my-zsh:
ga .

// 如果就想把所有倉庫下的更改加入也可以這樣:
git add --all
// Oh-my-zsh:
gaa
           

修改送出資訊

同分支名,有時發現拼寫錯誤或漏加了一些檔案。那我就通過以下指令修改:

git commit --am
// Oh-my-zsh
gc --am
           

把修改推送到遠端

如果推送的是個新分支,或是從來沒設定過遠端上遊分支的話,推薦使用

-u

設定上遊:

git push -u origin <分支名>
// Oh-my-zsh:
gpsup
           

然後就可以在檢視分支狀态時看到本地分支跟遠端分支的差異(就像在“檢視分支狀态”一節中提到的一樣)。并且下次推送的時候就不再需要這樣的操作了:

git push
// Oh-my-zsh:
gp
           

解決沖突

第一選項是rebase

當分支的修改量不大的時候,

rebase

是我的第一選項。因為它會確定我的更新是建立在最新代碼上的,避免很多問題。

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

rebase上遊可以通過

git pull

實作:

git pull --rebase
// Oh-my-zsh:
ggu
           

不過我更多情況下會rebase最新的主分支:

git rebase origin/master
// Oh-my-zsh:
grb origin/master
// 或
grbm
           

指定從

origin

這樣的上遊會確定git從遠端拉取最新的代碼再rebase。

Rebase或merge之前考慮先壓縮一下commits

有時我在開發中送出了多個小改動,這些送出在主分支中沒啥存在意義,或者存在一些對某個子產品的反複修改。然而這些commits會在我試圖rebase或者回過頭來檢視修改的緣由時造成一定的麻煩,是以我會考慮在合并代碼前将這些commits壓縮成一個。

如果在自己的分支,我隻想簡單地把所有此次修改壓縮成1個commit的話,我就:

  1. 通過合并請求看一下有多少commits(像這個),或在git log裡檢視 (參照檢視分支狀态 一節)
  2. git reset --soft HEAD~<commit數>

    git reset --soft <commit_SHA>

    (注意這兒的commit SHA是需要保留的最新的commit SHA)來把那些commits移除,所有改動恢複為staged狀态 - 需要注意的是reset一個合并分支的commit會同時reset所有被合并的commits,是以這裡的commit數量跟數出來的可能不同。
  3. gc -m <new_commit_message>

    來創新一個新的commit
  4. gp -f

    - 如果這些送出之前已經被推送到遠端,那這時因為我們修改了原本的git曆史樹結構,是以需要加

    -f

    來強制推送。這其實挺危險的,請確定這樣做的安全性。

如果需要保留原有的消息,和作者的資訊。那就考慮用git的互動模式:

  1. git rebase -i HEAD~<commit_counts>

    git rebase -i <commit_SHA>

  2. 然後它會打開指令行編輯器如

    vi

    :
    用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作
    根據提示資訊修改每行commit消息頭部的操作指令詞(打開時候都是

    pick

    )。

    假設這邊我就把3個送出合成1個,那我需要保持第一個commit為

    pick

    ,并修改剩餘兩個為

    squash

    s

  3. 儲存退出。修改成功則會顯示如下确認資訊編輯界面:
    用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作
  4. 再度儲存退出就完成了。

比較複雜的情況下選用merge

如果想更新一個共享分支(多人基于這個分支上開發),rebase就不是一個很好的選項,因為它會導緻所有基于它的其他分支都遇到很嚴重的沖突。

還有一種情況是在開發一個比較大的項目,為了更好地控制版本,特意分了多次送出。這時用rebase就會遇到需要多次解決代碼沖突,而我通常解決2個沖突之後就開始迷失自我不知道這是哪兒了。

這時用

merge

比較好:

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

如果隻是要合并上遊分支的話

git pull

就可以了:

git pull
// Oh-my-zsh:
gl
           

更多情況下我需要合并主分支, 那就用:

git merge origin/master
// Oh-my-zsh:
gm origin/master
           

解決沖突

一想到解決沖突就想到Webstorm那個超贊的沖突解決工具。但是,我幾年前還是抛棄了Webstorm,因為它特别能把我的記憶體和CPU吃光,系統異常卡頓,然後我一去不複返。這邊還因為沒有能媲美的工具導緻我有個比較長的适應期,現在感覺VSCode自帶的git工具也挺好的。

合并或rebase的時候,如果遇到沖突,切換到“SOURCE CONTROL”面闆點選“重新整理”圖示就能看到用“C”标注出來的沖突檔案:

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

選擇打開這些檔案,然後就在編輯器裡看到高亮顯示和

Current Change

Incoming Change

這些選項。講真,這比通常git工具顯示的

ours

theirs

要好了解多了。

這兒不太友善的地方是它是上下顯示的,而不是像Webstorm這樣左右比較的,是以在沖突區域大的時候就感覺不太好使了。這兒我暫時還沒有更好的辦法,也不想因為這個較少遇到的情況單獨裝個軟體,先就這樣用着吧。

為啥代碼寫成這樣

當有地方壞了或看起來很奇怪,這時有意義的送出資訊和可追溯的git曆史樹就顯得特别有用。這裡我超愛用VSCode的GitLens插件:

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

它提供了特别多的功能來幫我們檢視曆史,不過我幾乎隻用

LINE HISTORY

FILE HISTORY

來幫我了解這塊代碼是怎樣一步步變成現在的模樣的:

用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

清理不需要的分支

清理遠端的分支記錄

如果有在本地打開一些遠端分支,在這些分支被合并之後,本地關于這個分支的記錄是不會自動清理的。大多情況下這沒什麼,就讓它在那好了。但在大型代碼倉庫有一定幾率遇到奇怪的問題而導緻無法做任何git操作的麻煩。是以我會隔段時間清理一下:

git remote prune origin
// 或者可以用fetch來跑:
git fetch --all --prune
// Oh-my-zsh會比較友善:
gfa
           

本地分支的清理

本地分支清理起來比較麻煩。我有很長一段時間都隻依靠像這樣手動删:

git branch | cat  // 列印出所有本地分支
git branch -D <分支名>
           

後來我發現Oh-my-zsh的一個快捷指令,它可以删掉所有已經被合并到

master

/

develop

/

dev

的分支:

gbda
           
用指令行和VSCode插件高效使用git代碼倉庫、處理日常工作

繼續閱讀