只有在遇到問題的時候,才體會到技巧帶來的好處!

常見企業工作流程

主要介紹,企業中常用的 Git 工作流程!

Git Flow

主幹分支

穩定分支

開發分支

補丁分支

修改分支

學會 Git 這 11 條使用技巧,你離大拿就不遠了!

Github Flow

建立分支

新增提交

提交 PR 請求

討論和評估程式碼

部署檢測

合併程式碼

學會 Git 這 11 條使用技巧,你離大拿就不遠了!

Gitlab Flow

帶生產分支

帶環境分支

帶釋出分支

學會 Git 這 11 條使用技巧,你離大拿就不遠了!

日常使用最佳實踐

總結日常工作中應該遵循的 Git 使用方式和方法!

使用命令列代替圖形化介面

使用命令列來操作,簡潔且效率高

提交應該儘可能的表述提交修改內容

區分 subject 和 body 內容,使用空行隔開

subject 一般不超過 50 個字元

body 每一行的長度控制在 72 個字元

subject 結尾不需要使用句號或者點號結尾

body 用來詳細解釋此次提交具體做了什麼

使用 。gitignore 檔案來排除無用檔案

可使用模板檔案,然後根據專案實際進行修改

基於分支或 fork 的開發模式

不要直接在主幹分支上面進行開發

在新建的分支上進行功能的開發和問題的修復

使用 release 分支和 tag 標記進行版本管理

使用 release 分支釋出程式碼和版本維護(release/1。32)

使用 tag 來標記版本(A-大feature功能。B-小feature功能。C-只修bug)

常用命令彙總整理

日常使用只要記住 6 個命令就可以了。

學會 Git 這 11 條使用技巧,你離大拿就不遠了!

`# 工作區 -> 暫存區

$ git add

暫存區 -> 本地倉庫

$ git commit -m “some info”

本地倉庫 -> 遠端倉庫

$ git push origin master # 本地master分支推送到遠端origin倉庫

`

# 工作區 <- 暫存區

$ git checkout —— # 暫存區檔案內容覆蓋工作區檔案內容

# 暫存區 <- 本地倉庫

$ git reset HEAD # 本地倉庫檔案內容覆蓋暫存區檔案內容

# 本地倉庫 <- 遠端倉庫

$ git clone # 克隆遠端倉庫

$ git fetch upstream master # 拉取遠端程式碼到本地但不應用在當前分支

$ git pull upstream master # 拉取遠端程式碼到本地但應用在當前分支

$ git pull ——rebase upstream master # 如果平時使用rebase合併程式碼則加上

# 工作區 <- 本地倉庫

$ git reset # 本地倉庫覆蓋到工作區(儲存回退檔案內容修改)

$ git reset ——mixed # 本地倉庫覆蓋到工作區(儲存回退檔案內容修改)

$ git reset ——soft # 本地倉庫覆蓋到工作區(保留修改並加到暫存區)

$ git reset ——hard # 本地倉庫覆蓋到工作區(不保留修改直接刪除掉)

配置實用引數選項

雖然配置比較簡單,但是非常有用!

全域性配置

# 使用者資訊

$ git config ——global user。name “your_name”

$ git config ——global user。email “your_email”

# 文字編輯器

$ git config ——global core。editor “nvim”

# 分頁器

$ git config ——global core。pager “more”

# 別名

$ git config ——global alias。gs “git status”

# 糾錯

$ git config ——global help。autocorrect 1

個人配置

# 不加——global引數的話,則為個人配置

$ git config ——list

$ git config user。name

$ git config user。name “your_name”

# 如果在專案中設定,則儲存在。git/config檔案裡面

$ cat 。git/config

[user]

name = “your_name”

……

合併和變基的選擇

到底什麼時候使用 merge 操作,什麼時候使用 rebase 操作呢?

使用 merge 操作 - Python 中的 Requests 庫在使用

支援使用 merge 的開發者,他們認為倉庫的提交歷史就是記錄實際發生過什麼,它是針對於歷史的一個文件,本身其實是有價值的,我們不應該隨意修改。我們改變歷史的話,就相當於使用“謊言”來掩蓋實際發生過的事情,而這些痕跡是應該被保留的。可能,這樣並不是很好。

# 3rd的兩個分支的commit修改相同內容

* 62a322d - (HEAD->master) Merge branch ‘hotfix3’ into master

|

| * 6fa8f4a - (hotfix3) 3rd commit in hotfix3

* | 548d681 - 3rd commit in master

|/

* 6ba4a08 - 2nd commit

* 22afcc1 - 1st commit

使用 rebase 操作 - Python 中的 Django 庫在使用

支援使用 rebase 的開發者,他們認為提交歷史是專案過程中發生過的事情,需要專案的主幹非常的乾淨。而使用 merge 操作會生成一個 merge 的 commit 物件,讓提交歷史多了一些非常多餘的內容。

當我們後期,使用 log 命令參看提交歷史的話,會發現主幹的提交歷史非常的尷尬。比如,同樣的修改內容重複提交了兩次,這顯然是分支合併導致的問題。

# 3rd的兩個分支的commit修改相同內容

* 697167e - (HEAD -> master, hotfix) 3rd commit

* 6ba4a08 - 2nd commit (2 minutes ago)

* 22afcc1 - 1st commit (3 minutes ago)

兩者的使用原則

總的原則就是,只對尚未推送或分享給其他人的本地修改執行變基操作清理歷史,從不對已經推送到倉庫的提交記錄執行變基操作,這樣,你才可能享受到兩種方式帶來的便利。

更新倉庫提交歷史

Git 提供了一些工具,可以幫助我們完善版本庫中的提交內容,比如:

合併多個 commit 提交記錄

日常開發中,我們為了完成一個功能或者特性,提交很多個 commit 記錄。但是在最後,提交 PR 之前,一般情況下,我們是應該整理下這些提交記錄的。有些 commit 需要合併起來,或者需要將其刪除掉,等等。

# 調整最近五次的提交記錄

$ git rebase -i HEAD~5

$ git rebase -i 5af4zd35 # 往前第六次的commit值

reword c2aeb6e 3rd commit

squash 25a3122 4th commit

pick 5d36f1d 5th commit

fixup bd5d32f 6th commit

drop 581e96d 7th commit

# 檢視提交歷史記錄

$ git log

* ce813eb - (HEAD -> master) 5th commit

* aa2f043 - 3rd commit -> modified

* 6c5418f - 2nd commit

* c8f7dea - 1st commit

學會 Git 這 11 條使用技巧,你離大拿就不遠了!

刪除意外除錯的測試程式碼

有時候提交之後,我們才發現提交的歷史記錄中存在這一些問題,而這個時候我們又不想新生成一個 commit 記錄,且達到一個修改的目錄。即,修改之前的 commit 提交記錄。

# 不使用分頁器

$ git ——no-pager log ——oneline -1

d5e96d9 (HEAD -> master) say file

# 改變提交資訊並加入暫存區

$ echo “hello” > say。txt

$ git add -u

# 改變當前最新一次提交記錄

$ git commit ——amend

# 改變且息不改變提交信

$ git commit ——amend ——no-edit

# 改變當前最新一次提交記錄並修改資訊

$ git commit ——amend -m “some_info”

# 不使用分頁器

$ git ——no-pager log ——oneline -1

9e1e0eb (HEAD -> master) say file

取消多個 commit 中的部分提交

我們開發了一個功能,而在上線的時候,產品經理說這個功能的部分特性已經不需要了,即相關特性的提交記錄和內容就可以忽略/刪除掉了。

# 回滾操作(可多次執行回滾操作)

# 徹底上次提交記錄;也可是PR的提交記錄

# 預設會生成一個型別為reverts的新commit物件

$ git revert 3zj5sldl

[4] 合併某些特定的 commit 提交

我們不希望合併整個分支,而是需要合併該分支的某些提交記錄就可以了。

bash

# 摘櫻桃

$ git cherry-pick -x z562e23d

使用引用日誌記錄

如何找回我們丟失的內容和記錄?

我們之前說過,使用下面命令回退內容、強制推送程式碼、刪除本地分支,都是非常危險的操作,因為重置之後我們就沒有辦法在找到之前的修改內容了。

# 回退

$ git reset ——hard

# 推送

$ git push origin master -f

# 分支

$ git branch -D

其實 Git 給我們留了一個後門,就是使用 relflog 命令來找回之前的內容,只不過是相對來說麻煩一些。而原理也很簡答,就是在我們使用 Git 命令操作倉庫的時候,Git 偷偷地幫助我們把所有的操作記錄了下來。

# 檢視日誌記錄

$ git ——no-pager log ——oneline -1

4bc8703 (HEAD -> master) hhhh

# 回退到上次提交

$ git reset ——hard HEAD~1

# 檢視引用日誌記錄

$ git reflog

6a89f1b (HEAD -> master) HEAD@{0}: reset: moving to HEAD~1

4bc8703 HEAD@{1}: commit (amend): hhhh

# 找回內容

$ git cherry-pick 4bc8703

批次修改歷史提交

批次修改歷史提交雖然不常用,但是理解的話可以省下很多時間!

之前我們學習到的命令都是針對於一個或者多個 commit 提交資訊進行修改的,如果我們需要全域性修改歷史提交呢?當然,Git 中也是支援全域性修改歷史提交的,比如全域性修改郵箱地址,或者將一個檔案從全域性歷史中刪除或修改。

開源專案中使用了公司郵箱進行提交了

提交檔案中包含隱私性的密碼相關資訊

提交時將大檔案提交到了倉庫程式碼中了

這裡我們可以使用 filter-brach 的方式進行修改,但是建議在使用之前,新建一個分支,在上面進行測試沒有問題之後,再在主幹上操作,防止出現問題,背個大鍋在身上。

# 建立分支

$ git branch -b testing

# 修改郵箱地址

$ git filter-branch ——commit-filter ‘

if [ “$GIT_AUTHOR_EMAIL” == “escape@escapelife。site” ]; then

GIT_AUTHOR_NAME=“escape”;

GIT_AUTHOR_EMAIL=“escape@gmail。com”;

git commit-tree “$@”

else

git commit-tree “$@”

fi’ HEAD

靈活使用鉤子函式

主要介紹。git/hooks 目錄下面的示例鉤子函式!

在 Git 裡面有兩類,分別對應客戶端和服務端鉤子函式。客戶端的鉤子函式,是在執行提交和合並之類的操作時呼叫的。而服務端鉤子函式,就是當服務端收到程式碼提交之後,可以出發程式碼檢查和持續整合的步驟。作為開發者我們並不會搭建 Git 伺服器,所以基本不會涉及。

下面就是 Git 自帶的鉤子指令碼,但是自帶的都以 。sample 作為字尾,表示並沒有啟用,表示為一個示例。如果需要啟用的話,將 。sample 作為字尾刪除掉,即可。而其鉤子指令碼的對應內容,都是使用 Shell 語法進行編寫的。

➜ ll 。git/hooks

total 112

-rwxr-xr-x applypatch-msg。sample

-rwxr-xr-x commit-msg。sample

-rwxr-xr-x fsmonitor-watchman。sample

-rwxr-xr-x post-update。sample

-rwxr-xr-x pre-applypatch。sample

-rwxr-xr-x pre-commit。sample

-rwxr-xr-x pre-merge-commit。sample

-rwxr-xr-x pre-push。sample # 不會推送包含WIP的commit提交

-rwxr-xr-x pre-rebase。sample

-rwxr-xr-x pre-receive。sample

-rwxr-xr-x prepare-commit-msg。sample

-rwxr-xr-x update。sample

其實,鉤子指令碼使用任何語言編寫都是可以的,只要你讓程式返回對應的退出碼就可以了。

正常的程式碼合入流程就是,我們本地修改之後,提一個 PR 請求並透過 Github 的 CI 檢查,接下來進行程式碼評審,最後被合併入主幹。但是,好的一個習慣就是,在程式碼提交之前就應該保證程式碼不會出現語法錯誤等基礎問題,比如透過 flake8 和 PEP8 標準等。

這個時候我們就可以使用 pre-commit 這個 Github 的開源專案了,其本質就是給專案新增鉤子函式的一個指令碼,可以保證我們在提交程式碼或者推送程式碼之前,先檢查程式碼的質量。

而 pre-commit-hooks 這個專案裡面包含的就是,現在所支援的鉤子指令碼,即開箱即用的鉤子指令碼集合。而其鉤子指令碼的對應內容,都是使用 Python 語法進行編寫的。

# 安裝方式

$ pip install pre-commit

# 指定hook型別(即在哪裡檢查)

$ pre-commit install -f ——hook-type pre-push

# 配置需要執行的檢查

$ cat 。pre-commit-config。yaml

repos:

- repo: https://github。com/pre-commit/pre-commit-hooks

rev: v2。9。2

hooks:

- id: trailing-whitespace

- id: flake8

# 執行push操作時檢查

$ git push origin master

快速克隆大型專案

在大專案中工作中,拉取程式碼非常佔時間!

我們如果想為 Linux 或 Python 這樣的大型專案貢獻提交的時候,首先遇到的問題就是,如果快速的 clone 該專案到本地。因為改專案提交歷史超多且倉庫巨大,加了國內網路的問題,可能等專案完全拉下來的時候,我們的熱情都消減下去了。

好在 Git 也幫我們想到了這樣的問題,我們可以使用 ——depth 引數值拉取遠端倉庫上面最新一次的提交歷史,並不包含專案歷史記錄,即 。git/objects/ 目錄下的物件只是本地的,並不包含之前的多次修改產生的物件。

# 克隆不包含之前歷史

$ git clone http://xxx。xx。xxx/xxx ——depth=1

但是,有時間我們可能會需要 clone 倉庫中的某個 tag 版本對應下的內容。如果我們直接使用 clone 命令是無法做到的,需要執行如下操作,即可完美解決。

# 克隆特定版本程式碼

$ git init xxx-15-0-1

$ git remote add origin http://xxx。xx。xxx/xxx

$ git -c protocol。version=2 fetch origin 15。0。1 ——depth=1

$ git checkout FETCH_HEAD

上面的效果已經基本可以滿足我們日常使用需求了,但是不幸的是,你現在接受了一個機器學習的專案,裡面包含了大量的 lfs 檔案,現在 clone 又會變得非常慢。可以使用如下操作來避免,Git 工具主動拉去 lfs 檔案,來達到目錄。

# 克隆不包含LFS資料

$ GIT_LFS_SKIP_SMUDGE=1 git clone http://xxx。xx。xxx/xxx

如何處理工作中斷

如果在多路運轉的時候,還能夠高效的進行開發!

比如,我們現在正在一個分支為專案新增一個小的功能,此時,產品經理找到你說是線上環境現在有一個 bug 需要讓你來修復下。但是,此時我們新增的小功能並沒有完成。

如果此時,我們直接切換到主幹分支的話,會將之前分支沒有來得及提交的內容全部都帶到了主幹分支上來,這是我們不想看到的情況。此時,我們需要儲存上個分支的工作狀態,在我們修改完成線上 bug 之後,再繼續工作。

好在 Git 也幫我們想到了這樣的問題,我們可以使用 stash 子命令幫助我們將當前工作區、暫存區當中的修改都儲存到堆疊之中。等到需要處理的時候,再彈出堆疊中的內容,我們再次進行開發。

➜ git stash -h

usage: git stash list [

or: git stash show [] [

or: git stash drop [-q|——quiet] [

or: git stash ( pop | apply ) [——index] [-q|——quiet] [

or: git stash branch

or: git stash clear

or: git stash [push [-p|——patch] [-k|——[no-]keep-index] [-q|——quiet]

[-u|——include-untracked] [-a|——all] [-m|——message

[——pathspec-from-file= [——pathspec-file-nul]]

[——] [。。。]]

or: git stash save [-p|——patch] [-k|——[no-]keep-index] [-q|——quiet]

[-u|——include-untracked] [-a|——all] [

# 儲存當前的修改但不用提交commit

$ git stash

# 儲存當前狀態包括untracked的檔案

$ git stash -u

# 展示所有stashes資訊

$ git stash list

# 回到某個stash狀態

$ git stash apply

# 刪除儲藏區

$ git stash drop

# 回到最後一個stash的狀態並刪除這個stash資訊

$ git stash pop

# 刪除所有的stash資訊

$ git stash clear

# 從stash中拿出某個檔案的修改

$ git checkout ——

其實比較保險的做法就是,將當前的所有修改進行 push 並儲存到遠端倉庫裡面。這樣的好處在於,可以遠端備份我們的修改,不會害怕本地檔案丟失等問題。等到我們需要繼續開發的時候,拉下對應內容,再想辦法進行補救,比如使用 ——amend 或者 reset 命令。

# 將工作區和暫存區覆蓋最近一次提交

$ git commit ——amend

$ git commit ——amend -m “some_info”

# 回退到指定版本並記錄修改內容(——mixed)

# 本地倉庫覆蓋到工作區(儲存回退檔案內容修改)

$ git reset a87f328

$ git reset HEAD~

$ git reset HEAD~2

$ git reset ~2

$ git reset ——mixed

# 本地倉庫覆蓋到工作區(不保留修改直接刪除掉)

$ git reset ——soft

# 本地倉庫覆蓋到工作區(保留修改並加到暫存區)

$ git reset ——hard

作者: Escape

連結: https://www。escapelife。site/p。。。

推薦閱讀

備戰金三銀四跳槽季!面試準備與面試題總結已擼完(Linux系統運維篇)!

分享一些技術資料(架構、資料庫、java等),建議收藏!

升職加薪必備!運維工程師打怪升級進階成神之路

強大,10k+點讚的 SpringBoot 後臺管理系統竟然出了詳細教程!

分享一套基於SpringBoot和Vue的企業級中後臺開源專案,程式碼很規範!

能掙錢的,開源 SpringBoot 商城系統,功能超全,超漂亮!

如有錯誤或其它問題,歡迎小夥伴留言評論、指正。如有幫助,歡迎點贊+轉發分享。

更多相關開源技術文章,請持續關注:民工哥知乎技術專欄

我是民工哥,一個愛折騰的IT技術老司機,歡迎關注我,我們一起學習,共同成長!!