开发工具:Git超全实用技巧,值得收藏!
只有在遇到問題的時候,才體會到技巧帶來的好處!
常見企業工作流程
主要介紹,企業中常用的 Git 工作流程!
Git Flow
主干分支
穩定分支
開發分支
補丁分支
修改分支
Github Flow
創建分支
添加提交
提交 PR 請求
討論和評估代碼
部署檢測
合并代碼
Gitlab Flow
帶生產分支
帶環境分支
帶發布分支
日常使用最佳實踐
總結日常工作中應該遵循的 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?add?<file/dir>
#?暫存區?->?本地倉庫
$?git?commit?-m?"some?info"
#?本地倉庫?->?遠程倉庫
$?git?push?origin?master??#?本地master分支推送到遠程origin倉庫
配置實用參數選項
雖然配置比較簡單,但是非常有用!
全局配置
#?用戶信息 $?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刪除意外調試的測試代碼
有時候提交之后,我們才發現提交的歷史記錄中存在這一些問題,而這個時候我們又不想新生成一個 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?<commit>#?推送 $?git?push?origin?master?-f#?分支 $?git?branch?-D?<branch_name>其實 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"?];?thenGIT_AUTHOR_NAME="escape";GIT_AUTHOR_EMAIL="escape@gmail.com";git?commit-tree?"$@"elsegit?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-hooksrev:?v2.9.2hooks:-?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?[<options>]or:?git?stash?show?[<options>]?[<stash>]or:?git?stash?drop?[-q|--quiet]?[<stash>]or:?git?stash?(?pop?|?apply?)?[--index]?[-q|--quiet]?[<stash>]or:?git?stash?branch?<branchname>?[<stash>]or:?git?stash?clearor:?git?stash?[push?[-p|--patch]?[-k|--[no-]keep-index]?[-q|--quiet][-u|--include-untracked]?[-a|--all]?[-m|--message?<message>][--pathspec-from-file=<file>?[--pathspec-file-nul]][--]?[<pathspec>...]]or:?git?stash?save?[-p|--patch]?[-k|--[no-]keep-index]?[-q|--quiet][-u|--include-untracked]?[-a|--all]?[<message>] #?存儲當前的修改但不用提交commit $?git?stash#?保存當前狀態包括untracked的文件 $?git?stash?-u#?展示所有stashes信息 $?git?stash?list#?回到某個stash狀態 $?git?stash?apply?<stash@{n}>#?刪除儲藏區 $?git?stash?drop?<stash@{n}>#?回到最后一個stash的狀態并刪除這個stash信息 $?git?stash?pop#?刪除所有的stash信息 $?git?stash?clear#?從stash中拿出某個文件的修改 $?git?checkout?<stash@{n}>?--?<file-path>其實比較保險的做法就是,將當前的所有修改進行 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?<tag>~2 $?git?reset?--mixed?<commit/reference>#?本地倉庫覆蓋到工作區(不保留修改直接刪除掉) $?git?reset?--soft?<commit/reference> #?本地倉庫覆蓋到工作區(保留修改并加到暫存區) $?git?reset?--hard?<commit/reference>IT技術分享社區
個人博客網站:https://programmerblog.xyz
文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠程辦公:常用的遠程協助軟件,你都知道嗎?51單片機程序下載、ISP及串口基礎知識硬件:斷路器、接觸器、繼電器基礎知識
總結
以上是生活随笔為你收集整理的开发工具:Git超全实用技巧,值得收藏!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: flash builder 序列号
- 下一篇: java excel换行_Java 导出