[譯] 我無法想象沒有 Git 別名的的場景

Starrier發表於2018-12-24

我無法想象沒有 Git 別名的的場景

大家看到我的 Git 工作流時,總是充滿了驚訝與好奇:

我的 Git 工作流

我的 Git 工作流

我對別名的熱愛,始於我初次下載 zsh 和它的 oh-my-zsh 套件。它包含大量針對不同命令列程式的預定義別名和幫助函式。我立刻便喜歡上了這種取代常規的那些很長的引數化呼叫的輸入概念。因為我最常使用的工具是 Git,所以它是我開始別名變革的首選目標。幾年之後的現在,我無法想象使用 Git 自帶的那些原始 git 命令。

當然,Git 本身就擁有完美的別名自定義系統。對我來說,我只是不喜歡 git 和別名之間的空白。Shell 別名也很靈活並且還可以用於其他命令列,例如 docker

下面你會找到我使用最多的別名列表。其中一些直接源自於 oh-my-zsh,其他一些是我自己創造的。我喜歡你們至少可以找到一些有用的!如果你想親自嘗試所有的這些方法,可以從我的倉庫下載。

1. 我們從這個庫開始吧!

alias gcl = git clone

這可能不是 Git 使用者最常使用的命令,但我個人希望儘快讓你們掌握這些令人生畏的 GitHub 專案,就像我所希望的那樣。

2. 從遠端倉庫獲取分支最新動態

alias gf = git fetch

我通常使用 fetch 來獲取遠端倉庫的最新更改,因為它不會以任何形式影響工作目錄的 HEAD。之後我會使用其他命令來顯式修改本地檔案。

3. 我們檢視一下其他分支!

alias gco = git checkout

對於日常開發來說,這無疑是最有用的命令之一。我決定寫這篇文章的原因之一就是發現大家每次在他們想要切換分支時,仍然需要使用 git checkout

4. 回退到之前的分支狀態!

gco -

這個破折號是一個小把戲,意思是“以前的分支”。我知道嚴格意義上,它不算是別名,但它太過有用以至於不得不提。而且,我印象中沒有多少人知道它。

checkout 不是接受破折號的唯一選項 —— 你也可以在其他地方使用,比如 mergecherry-pickrebase

5. 快速切換至 master 分支

alias gcm = git checkout master

如果我們經常在一些有明確定義的的分支之間進行切換,那麼我們為什麼不使其儘可能簡單一些呢?根據你的工作流,你也可以找出其他相似的有用別名:gcd (develop)、gcu (uat)、gcs (stable)。

6. 我在哪?發生了什麼?

alias gst = git status

簡單明瞭。

7. 我不在意當前工作變化,只要從源分支給我最新的狀態就行!

alias ggrh = git reset --hard origin/$(current_branch)

我的個人最愛。有多少次你製造瞭如此嚴重的混亂,以至於你只想讓暫存區和工作目錄恢復到原來的狀態?現在只剩下四個按鍵了。

請注意,這個特定的命令將當前分支重置為來源於 origin 分支的最新提交。這正是通常最需要的,但可能不是需要的東西。每當我不關心本地更改時,我都會使用它,我只希望我的當前分支能夠反映對應的遠端分支。你可能會說你可以使用 git pull 替帶,但我只是不喜歡它會試圖合併遠端分支,而不只是將當前分支重置為遠端分支。

注意 current_branch 是一個自定義函式(由 oh-my-zsh 作者建立)。你可以在這裡看到它。

8. 當前的更改是什麼?

alias gd = git diff

有一個典型示例。它只是顯示了所有的改變,但並沒有分階段。如果要檢視已經進行的更改,請使用此版本:

alias gdc = git diff --cached

9. 讓我們提交那些更改的檔案!

alias gca = git commit -a

這會提交所有的更改檔案,因此你不需要手動新增它們。但是,如果有一些尚未提交的新檔案,顯然需要顯式地說明它們:

alias ga = git add

10. 我想在先前的提交中新增一些更改!

alias gca! = git commit -a --amend

我經常使用它,因為我喜歡保持 Git 歷史記錄的整潔(沒有 “pull request fixs” 或者 “forgot to add this file” 型別的提交資訊)。它只需簡單接受所有的更改並將他們新增到上一次提交中。

11. 我之前的分支做的太快,那麼怎麼“撤銷”一個檔案?

gfr() {
    git reset @~ "$@" && git commit --amend --no-edit
}
複製程式碼

這是一個函式,不是別名,乍看好像有些複雜。它獲取要“取消提交”的檔名稱,從 HEAD 提交中刪除對該檔案所做的所有更改,但將其保留在工作目錄中。然後,它會準備分階段提交,也許是作為一個獨立提交。這就是它在實踐中的工作方式:

grf 示例

12. 好的,準備推送!

alias ggpush = git push origin $(current_branch)

我每次想推送的時候,都會使用這個。因為它是隱式傳遞遠端分支引數,所以我可以確保只推送一個分支,而無須在意 push.default 設定。從 Git 2.0 開始,它會成為預設行為,但是別名為我提供了額外的安全保證,以防我使用一些 Git 遺留的版本問題。

對於正常的推送,這可能並不那麼重要,但對於下一個命令來說,這非常關鍵。

13. 我已經準備推送了,而且我知道我在做什麼

alias ggpushf = git push --force-with-lease origin $(current_branch)

強制推送顯然是一個有爭議的習慣,許多人會說你永遠不應該這樣做。我同意,但只有涉及到分享像 master 這樣的分支時才會有問題。

正如我提及的,我喜歡保持我的 git 歷史乾淨。這有時涉及更改已經被推送的提交。這時,--force-with-lease 就會特別有用,因為當你的本地倉庫沒有更新到遠端分支的最新狀態時,它會拒絕推送。因此,它不可能拋棄別人的修改,至少不會在無意中拋棄。

在我的同事有一次錯誤地呼叫了 git commit -f(將 push.default 設定為 matching)之後,我開始使用這個別名,將遠端分支部分名稱設定為 $(current_branch),並強制推送所有的本地分支到 origin 分支。包括一箇舊版本的 master,當他意識到發生了什麼之後,我仍然記得他眼中的恐慌。

14. 哇,推送被拒絕了!有人動了我的分支!

你試圖將你的分支推送到遠端倉庫,但得到了一下資訊:

To gitlab.com:mjkonarski/my-repo.git
 ! [rejected]        my-branch -> my-branch (non-fast-forward)
error: failed to push some refs to 'git@gitlab.com:mjkonarski/my-repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again. 
複製程式碼

當多個人同時在一個分支上工作時,就會發生這種情況。也許你的同事在你不知情的情況下,又推送了一個修改?或者你用了兩臺電腦,同步了之前的分支?一下是一個簡單的解決方案:

alias glr = git pull --rebase

它會自動拉取最新的修改,然後將你的提交 rebase 到他們的頂部。如果你足夠幸運(並且對不同的檔案進行了遠端修改),你甚至可以避免解決衝突。哇,又要重新推送!

15. 我想用自己的分支來對映主分支的最新變化!

假設你有一個分支是不久之前從 master 分支建立的。你已經推送了一些改變,但同時也更新了 master 本身。現在,你希望你的分支可以反映那些最新的提交內容。在這種情況下,相比 merge,我更喜歡 rebase —— 你的提交歷史保持保持簡短和清晰。就像打字一樣簡單:

alias grbiom = git rebase --interactive origin/master

我經常使用這個命令,因此這個別名是我最開始使用的第一批命令之一。--interactive 啟用了你最愛的編輯器,並允許你快速檢查即將基於 master 提交的提交列表。你也可以利用這個機會來 squashreword 或者 reorder 提交。因此有許多簡單別名可以選擇!

16. emmm,我嘗試了 rebase,但出現了嚴重的衝突!救命啊!

沒有人喜歡這些資訊:

CONFLICT (content): Merge conflict in my_file.md

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
複製程式碼

有時,你可能只想中止整個程式,之後再解決衝突。以上資訊是如何處理的線索,但為什麼需要這麼多按鍵呢?

alias grba = git rebase --abort

我們又安全了。當你終於鼓起勇氣再次進行合併解決這些衝突時,在 git add 之後,你只需繼續進行 rebase 輸入即可:

alias grbc = git rebase --continue

17. 請把這些變化暫時擱淺!

假設你已經做了一些改變,但還沒有提交它們。現在你想快速切換到另一個分支,並執行一些無關的工作:

alias gsta = git stash

這個提交將你的修改放在一邊,並恢復至 HEAD 的乾淨狀態。

18. 現在,開始回退!

當你完成了與你無關的工作時,你可能會快速回退你的修改:

alias gstp = git stash pop

19. 這個小提交,看起來很棒,讓我們把它放到自己的分支上!

Git 有一個叫做 cherry-pick 的優秀功能。你可以使用它來將任何現有提交新增到當前分支的頂部。它就像使用這個別名一樣簡單:

alias gcp = git cherry-pick

這當然會導致衝突,當然這也取決於你提交的內容。解決這個衝突與解決 rebase 衝突的方法完全一樣。因此,我們也有類似的選擇來中止以及繼續選擇分支:

alias gcpa = git cherry-pick --abort

alias gcpc = git cherry-pick --continue


以上列表肯定沒有涵蓋所有 git 用例。我想鼓勵你把它看作是建立你自己的化名套件的良好開端。在日常工作流程中尋求可能的改進是一個好主意。

你可以在我的 Github 倉庫看到這些別名(甚至更多)。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章