10個節(jié)省時間和改善工作流的Git技巧
這 10 個 Git 小技巧,不僅可以節(jié)省時間,而且能改善你的工作流程。
根據(jù)手冊,Git 被定義為傻瓜式內(nèi)容追蹤器,它功能豐富,但有些功能卻讓人望而生畏。因此,我們只是重復(fù)使用那幾個被記住的命令,而沒有充分使用。
https://manpages.debian.org/stretch/git-man/git.1.en.html
技巧 1:優(yōu)化配置
Git 在全局、用戶和本地級別上都是高度可配置的。
https://git-scm.com/docs/git-config
查找順序
每個設(shè)置都可以被覆蓋:
- $CWD/.git/config
- ▼ ▼ ▼
- $HOME/.gitconfig`
- ▼ ▼ ▼
- $HOME/.config/git/config
- ▼ ▼ ▼
- /etc/gitconfig
修改設(shè)置
用你喜歡的編輯器或者 CLI 編輯任何配置文件:
- # 全局設(shè)置
- git config --global <keypath> <value>
- # 本地設(shè)置
- git config <keypath> <value>
如果值包含空格字符,則需要用引號引起來。
顯示當(dāng)前設(shè)置
- # 顯示當(dāng)前設(shè)置及其來源
- git config --list --show-origin
一些有用的配置
- # 設(shè)定身份
- git config --global user.name "<your name>"
- git config --global user.email <your email>
- # 首選編輯器
- git config --global core.editor vim
- # 證書緩存
- # WINDOWS
- git config --global credential.helper manager
- # LINUX (超時時間——以秒為單位)
- git config --global credential.helper "cache --timeout=3600"
- # MACOS
- git config --global credential.helper osxkeychain
https://git-scm.com/docs/gitcredentials
技巧 2:別名(alias)
創(chuàng)建一個別名來保存常用的 git 命令:
- # 創(chuàng)建別名
- git config --global alias.<alias-name> "<git command>"
- # 使用別名
- git <alias-name> <more optional arguments>
一些有用的別名
- # 撤銷上次提交
- git config --global alias.undo "reset --soft HEAD^"
- # 將暫存區(qū)更新修訂到上次提交 (不改變提交信息)
- git config --global alias.amend "commit --amend --no-edit"
- # 壓縮的狀態(tài)輸出
- git config --global alias.st "status -sb"
- # 用 GRAPH 為日志著色
- git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'"
- # 刪除所有已合并的分支
- git config --global alias.rmb "!git branch --merged | grep -v '*' | xargs -n 1 git branch -d"
- # 貢獻(xiàn)排行
- git config --global alias.rank "shortlog -n -s --no-merges"
技巧 3:查找 Commits 和更改
通過 Commits 信息查找
- # 通過 commit 信息查找 (所有分支)
- git log --all --grep='<search term>'
- # 通過 commit 信息查找 (包含 reflog)
- git log -g --grep='<search term>'
通過更改查找
- # 通過更新的內(nèi)容查找
- git log -S '<search term>'
通過日期查找
- # 通過日期范圍查找
- git log --after='DEC 15 2019' --until='JAN 10 2020'
技巧 4:添加 hunk
git add <filepath>不僅能添加文件的所有變更,--path / -p參數(shù)還可以交互式暫存區(qū)塊。
- # 補(bǔ)丁命令
- y = 暫存區(qū)塊
- n = 不暫存這個區(qū)塊
- q = 退出
- a = 暫存當(dāng)前文件的此區(qū)塊以及所有剩余區(qū)塊
- d = 不暫存當(dāng)前文件的此區(qū)塊以及所有剩余區(qū)塊
- / = 查找區(qū)塊 (正則表達(dá)式)
- s = 劃分成更小的區(qū)塊
- e = 手動編輯區(qū)塊
- ? = 打印幫助說明
- g = 選擇要前往的區(qū)塊
- j = 將區(qū)塊設(shè)為未定,查看下一個未定區(qū)塊
- J = 將區(qū)塊設(shè)為未定,查看下一個區(qū)塊
- k = 將區(qū)塊設(shè)為未定,查看上一個未定區(qū)塊
- J = 將區(qū)塊設(shè)為未定,查看下一個區(qū)塊
https://git-scm.com/docs/git-add#Documentation/git-add.txt--i
技巧 5:儲藏(stash)更改而不提交
stash 將當(dāng)前的更改臨時擱置起來。在它的幫助下,可以返回當(dāng)前狀態(tài)的索引,并能在稍后應(yīng)用已儲藏的更改。
默認(rèn)情況下,僅儲藏當(dāng)前跟蹤文件中的更改,新文件將被忽略。
我們可以獨立地創(chuàng)建和應(yīng)用多個 stash。
https://git-scm.com/docs/git-stash
創(chuàng)建
- # 創(chuàng)建新的 STASH
- git stash
- # 創(chuàng)建新的 STASH (包含未追蹤的更改)
- git stash -u/--include-untracked
- # 創(chuàng)建新的 STASH 并命名
- git stash save "<stash name>"
- # 交互式儲藏
- git stash -p
羅列
- # 列出所有的 STASH (為其他命令提供"n")
- git stash list
瀏覽
- # 瀏覽 STASH 內(nèi)容
- git stash show
- # 瀏覽 STASH 差異
- git stash show -p
應(yīng)用
- # 應(yīng)用上一個 STASH (刪除 stash)
- git stash pop
- # 應(yīng)用上一個 STASH (保留 stash)
- git stash apply
- # 應(yīng)用特定的 STASH (n = stash 列表序號)
- git stash pop/apply stash@{n}
- # 從 STASH 創(chuàng)建新的分支 (n = stash 列表序號)
- git stash branch <new branch name> stash@{n}
- # 從 STASH 應(yīng)用單個文件 (n = stash 列表序號)
- git checkout stash@{n} -- <filepath>
清理
- # 刪除特定的 STASH (n = stash 列表序號)
- git stash drop stash@{n}
- # 刪除所有的 STASH
- git stash clear
技巧 6:空運行(Dry Run)
許多 git 操作可能具有破壞性,例如,git clean -f將刪除所有未跟蹤的文件,而且無法恢復(fù)。
要避免出現(xiàn)這種災(zāi)難性的結(jié)果,許多命令都支持dry-run,可以在實際產(chǎn)生結(jié)果前對其進(jìn)行檢查。不過遺憾的是,使用的選項不完全一致:
- git clean -n/--dry-run
- git add -n/--dry-run
- git rm -n/--dry-run
- # GIT MERGE 模擬 DRY-RUN
- git merge --no-commit --no-ff <branch>
- git diff --cached
- git merge --abort
請注意,git commit -n根本不是dry-run!它實際上是--no-verify,作用是忽略所有pre-commit/commit-msg githooks。
技巧 7:安全強(qiáng)制推送
在處理舊的 commit、創(chuàng)建新的 head 等情況時時很容易弄亂分支。git push --force可以覆蓋遠(yuǎn)程變更,但不應(yīng)該這樣做!
git push --force是一種具有破壞性且危險的操作,因為它無條件生效,并且會破壞其他提交者已經(jīng)推送的所有 commit。這對于其他人的代碼倉庫來說不一定是致命的,但是改變歷史記錄并影響其他人并不是一個好主意。
更好的選擇是使用git push --force-with-lease。
git 不會無條件地覆蓋上游的遠(yuǎn)程倉庫,而是檢查是否有本地不可用的遠(yuǎn)程更改。如果有,它會失敗并顯示一條“stale info”消息,并告訴我們需要先運行g(shù)it fetch。
https://git-scm.com/docs/git-push#Documentation/git-push.txt---force-with-leaseltrefnamegt
技巧 8:修改 commit 信息
Commit 是不可變的,且不能更改。不過可以用一條新的 commit 信息修訂現(xiàn)有的 commit,這會覆蓋原始 commit,因此請勿在已推送的 commit 中使用它。
- git commit --amend -m "<new commit message>"
https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---amend
技巧 9:修改歷史
修改代碼倉庫的歷史不僅限于修改上次提交信息,使用git rebase可以修改多個提交:
- # 提交的范圍
- git rebase -i/--interactive HEAD~<number of commits>
- # 該 hash 之后的所有提交
- git rebase -i/--interactive <commit hash>
在配置的編輯器中倒序列出所有的 commit,像這樣:
- # <command> <commit hash> <commit message>
- pick 5df8fbc revamped logic
- pick ca5154e README typos fixed
- pick a104aff added awesome new feature
通過更改編輯器中的實際內(nèi)容,可以為 git 提供一個方案,來說明如何進(jìn)行 rebase:
- # p, pick = 使用提交而不更改
- # r, reword = 修改提交信息
- # e, edit = 編輯提交
- # s, squash = 匯合提交
- # f, fixup = 類似"squash",但是會丟棄提交信息
- # x, exec = 運行命令 (其余行)
- # d, drop = 移除提交
保存編輯器后,git 將運行該方案以重寫歷史記錄。e, edit會暫停 rebase,就可以編輯代碼倉庫的當(dāng)前狀態(tài)。完成編輯后,運行g(shù)it rebase --continue。
如果過程中出現(xiàn)問題(例如合并沖突),我們需要重新開始,可以使用git rebase --abort。
https://git-scm.com/docs/git-rebase
技巧 10:存檔跟蹤文件
可以使用不同格式(zip或tar)來壓縮特定引用的跟蹤文件:
- git archive --format <format> --output <filename> <ref>
<ref>可以是一個分支、commit hash 或者一個標(biāo)簽。
https://git-scm.com/docs/git-archive
額外提醒:單破折號
有一個快捷方式可以表示剛用過的分支:一個單破折號-
- git checkout my-branch
- # 當(dāng)前分支:my-branch
- <do some git operations, e.g. adding/commiting>
- git checkout develop
- # 當(dāng)前分支:develop
- git merge -
- # 將 my-branch 合并到 develop
單破折號等同于@{-1}。
https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt-ltbranchgt
總結(jié)
Git 還有很多話題可談,這里只涉及一些皮毛。在另一篇文章中,我想展示如何用git bisect有效查找損壞的 commit,或者如何通過git reflog來運用任意git操作的完整歷史記錄。