Git 实用技巧记录,看这篇你就明白了!
“
只有在遇到問題的時候,才體會到技巧帶來的好處!
如果我們希望能夠快速了解或體驗一下 Git 的操作的話,我這里推薦搭建前往這個網站進行學習,其不需要我們安裝工具,而且我們的每一步操作都可以在右側實時看到狀態,對于我們學習和理解 Git 工作方式和原理非常有幫助的。—— 歡迎光臨 => https://oschina.gitee.io/learn-git-branching/
常見企業工作流程
主要介紹,企業中常用的 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?checkout?--?<file>??#?暫存區文件內容覆蓋工作區文件內容#?暫存區?<-?本地倉庫 $?git?reset?HEAD?<file>???#?本地倉庫文件內容覆蓋暫存區文件內容#?本地倉庫?<-?遠程倉庫 $?git?clone?<git_url>????????#?克隆遠程倉庫 $?git?fetch?upstream?master??#?拉取遠程代碼到本地但不應用在當前分支 $?git?pull?upstream?master???#?拉取遠程代碼到本地但應用在當前分支 $?git?pull?--rebase?upstream?master??#?如果平時使用?rebase?合并代碼則加上#?工作區?<-?本地倉庫 $?git?reset?<commit>??????????#?本地倉庫覆蓋到工作區(保存回退文件內容修改) $?git?reset?--mixed?<commit>??#?本地倉庫覆蓋到工作區(保存回退文件內容修改) $?git?reset?--soft?<commit>???#?本地倉庫覆蓋到工作區(保留修改并加到暫存區) $?git?reset?--hard?<commit>???#?本地倉庫覆蓋到工作區(不保留修改直接刪除掉)配置實用參數選項
雖然配置比較簡單,但是非常有用!
全局配置
#?用戶信息 $?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| 1 | p/pick | 使用這個 commit 記錄 |
| 2 | r/reword | 使用這個 commit 記錄;并且修改提交信息 |
| 3 | e/edit | 使用這個 commit 記錄;rebase 時會暫停允許你修改這個 commit |
| 4 | s/squash | 使用這個 commit 記錄;會將當前 commit 與上一個 commit 合并 |
| 5 | f/fixup | 與 squash 選項相同;但不會保存當前 commit 的提交信息 |
| 6 | x/exec | 執行其他 shell 命令 |
| 7 | d/drop | 移除這個 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合并某些特定的?commit?提交
我們不希望合并整個分支,而是需要合并該分支的某些提交記錄就可以了。
#?摘櫻桃 $?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[1]?這個 GitHub 的開源項目了,其本質就是給項目添加鉤子函數的一個腳本,可以保證我們在提交代碼或者推送代碼之前,先檢查代碼的質量。
而 pre-commit-hooks[2]?這個項目里面包含的就是,現在所支持的鉤子腳本,即開箱即用的鉤子腳本集合。而其鉤子腳本的對應內容,都是使用 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>相關鏈接:
https://github.com/pre-commit/pre-commit
https://github.com/pre-commit/pre-commit-hooks
IT技術分享社區
個人博客網站:https://programmerblog.xyz
文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠程辦公:常用的遠程協助軟件,你都知道嗎?51單片機程序下載、ISP及串口基礎知識硬件:斷路器、接觸器、繼電器基礎知識
總結
以上是生活随笔為你收集整理的Git 实用技巧记录,看这篇你就明白了!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 保存到本地_手把手教你将微信表情包保存到
- 下一篇: ms查约束具体代码_ECCV 2020附