收藏!工作中Git使用實(shí)踐和常用命令流程合集
Python實(shí)戰(zhàn)社群
Java實(shí)戰(zhàn)社群
長按識別下方二維碼,按需求添加
掃碼關(guān)注添加客服
進(jìn)Python社群▲
掃碼關(guān)注添加客服
進(jìn)Java社群▲
作者丨匠心Java
來源丨匠心Java
工作中g(shù)it是一項(xiàng)必不可少的技能,在項(xiàng)目的開發(fā)進(jìn)程中起著至關(guān)重要的作用
下面介紹一些git在工作中的一些使用實(shí)踐、常用流程、常用命令,供大家參考!
一:前言
Git的定義是:分布式版本控制系統(tǒng),用于項(xiàng)目開發(fā)中的版本控制。
從本質(zhì)上來講 Git 是一個內(nèi)容尋址(content-addressable)文件系統(tǒng),并在此之上提供了一個版本控制系統(tǒng)的用戶界面。
Git 的核心部分是一個簡單的鍵值對數(shù)據(jù)庫(key-value data store)。你可以向該數(shù)據(jù)庫插入任意類型的內(nèi)容,它會返回一個鍵值,通過該鍵值可以在任意時(shí)刻再次檢索(retrieve)該內(nèi)容。
git管理的項(xiàng)目工作目錄下的每一個文件都不外乎這兩種狀態(tài):已跟蹤或未跟蹤。
已跟蹤的文件是指那些被納入了版本控制的文件,在上一次快照中有它們的記錄,在工作一段時(shí)間后,它們的狀態(tài)可能處于未修改,已修改或已放入暫存區(qū)。
工作目錄中除已跟蹤文件以外的所有其它文件都屬于未跟蹤文件,它們既不存在于上次快照的記錄中,也沒有放入暫存區(qū)。
初次克隆某個倉庫的時(shí)候,工作目錄中的所有文件都屬于已跟蹤文件,并處于未修改狀態(tài)。
Git 保存的不是文件的變化或者差異,而是一系列不同時(shí)刻的文件快照。
在進(jìn)行提交操作時(shí),Git 會保存一個提交對象(commit object)。該提交對象會包含一個指向暫存內(nèi)容快照的指針。但不僅僅是這樣,該提交對象還包含了作者的姓名和郵箱、提交時(shí)輸入的信息以及指向它的父對象的指針。
二:git存儲
git將項(xiàng)目的存儲分為4部分,每部分有自己作用,見下圖:(圖片來自:博客)
Workspace:工作區(qū)(當(dāng)前用戶操作修改的區(qū)域)Index/Stage:暫存區(qū) (add后的區(qū)域)Repository:倉庫區(qū)或本地倉庫(commit后的區(qū)域)Remote:遠(yuǎn)程倉庫(push后的區(qū)域)
整體過程可以簡述為:
工作區(qū)-->?
add-->暫存區(qū)-->?commit-->本地倉庫區(qū)-->?push-->遠(yuǎn)程倉庫區(qū)遠(yuǎn)程倉庫區(qū)-->?
fetch-->使用refs\remotes下對應(yīng)分支文件記錄遠(yuǎn)程分支末端commit_id 和 本地倉庫區(qū) -->?merge-->工作區(qū)遠(yuǎn)程倉庫區(qū)-->?
pull-->使用refs\remotes下對應(yīng)分支文件記錄遠(yuǎn)程分支末端commit_id and 本地倉庫區(qū) and 工作區(qū)
git pull和git fetch有什么不同呢?下面簡單說一下
想要知道他們得不同,我們需要先了解兩個概念
FETCH_HEAD:可以看做是一個版本鏈接,記錄在本地的refs\remotes下對應(yīng)分支文件中,指向著目前已經(jīng)從遠(yuǎn)程倉庫取下來的分支的最新版本的commit_id。commit-id:在每次本地commit來保存當(dāng)前工作到本地倉庫區(qū)后, 會產(chǎn)生一個commit-id,這是一個能唯一標(biāo)識一個版本的序列號。在使用git push后,這個序列號還會同步到遠(yuǎn)程倉庫。
所以他們之間的不同在于:
git pull?直接將遠(yuǎn)程分支的修改更新到本地倉庫區(qū)和本地工作區(qū),我們就可以在本地工作區(qū)中看到最新代碼git fetch?只將遠(yuǎn)程分支的修改拉取到本地倉庫,并更新到FETCHHEAD,記錄遠(yuǎn)程分支最新的commitid,不會更新本地工作區(qū)代碼,只有使用了?git merge?才會將提交更新到本地倉庫區(qū)和工作區(qū)
其他想要了解更多git內(nèi)部消息請移步我的另一篇博文:git內(nèi)部存儲實(shí)現(xiàn)機(jī)制
在 git status中的體現(xiàn),見下圖:
Changesto be committed::代表被add的文件,被加載到了暫存區(qū)Changesnotstagedforcommit:代表在當(dāng)前分支中被修改的文件,還沒有被add,存儲在工作區(qū)Untrackedfiles?:代表不被git追蹤的文件,可以理解為不被git管理的文件如果沒有Changes to be committed和Changes not staged for commit說明現(xiàn)階段所有的修改已經(jīng)被commit到本地倉庫
如果git status后出現(xiàn)下述情況,說明還有已經(jīng)的commit到本地倉庫的還未被push到遠(yuǎn)程倉庫
$ git status
On branch master
Your branch is ahead of 'origin/master'by2 commits.
(use"git push" to publish your local commits)
Git 作為一個系統(tǒng),是以它的一般操作來管理并操縱(HEAD、index、Working Directory)三棵樹的
HEAD:?是當(dāng)前分支引用的指針,它總是指向該分支上的最后一次提交。這表示 HEAD 將是下一次提交的父結(jié)點(diǎn)。通常,理解 HEAD 的最簡方式,就是將它看做 你的上一次提交的快照。index:?index索引是你的 預(yù)期的下一次提交。我們也會將這個概念引用為 Git 的 “暫存區(qū)域”,這就是當(dāng)你運(yùn)行 git commit 時(shí) Git 看起來的樣子。Git 將上一次檢出到工作目錄中的所有文件填充到索引區(qū),它們看起來就像最初被檢出時(shí)的樣子。之后你會將其中一些文件替換為新版本,接著通過 git commit 將它們轉(zhuǎn)換為樹來用作新的提交。WorkingDirectory:最后,你就有了自己的工作目錄。另外兩棵樹以一種高效但并不直觀的方式,將它們的內(nèi)容存儲在 .git 文件夾中。工作目錄會將它們解包為實(shí)際的文件以便編輯。
如下圖:
?
三:git提交規(guī)則
首先,有個問題需要確認(rèn)一下,提交信息是使用中文還是英文呢?
如果你的項(xiàng)目是開源項(xiàng)目并且面向國際的開源項(xiàng)目,類似于阿里的Druid\PingCAP的TiDB等,那么一定要是用英文提交信息的!如果你的項(xiàng)目是公司內(nèi)部使用或者只會被公司內(nèi)部開發(fā)修改,那么中文也是不錯的,更加便于查看和管理。當(dāng)然,開發(fā)組中的英文能力都不錯的話,用英文也是可以的。
分支Branch管理:如果沒有一個好的branch管理的話,可能會有下述圖的情況,刺不刺激~
推薦的分支管理:
master?分支為主分支(保護(hù)分支),禁止直接在master上進(jìn)行修改代碼和提交,此分支的代碼可以隨時(shí)被發(fā)布到線上;develop?分支為測試分支或者叫做合并分支,所有開發(fā)完成需要提交測試的功能合并到該分支,該分支包含最新的更改;feature?分支為開發(fā)分支,大家根據(jù)不同需求創(chuàng)建獨(dú)立的功能分支,開發(fā)完成后合并到develop分支;fix?分支為bug修復(fù)分支,需要根據(jù)實(shí)際情況對已發(fā)布的版本進(jìn)行漏洞修復(fù);
標(biāo)簽Tag管理:Tag采用三段式:v版本.里程碑.序號(v2.3.1)
架構(gòu)升級或架構(gòu)重大調(diào)整,修改第1位
新功能上線或者模塊大的調(diào)整,修改第2位
bug修復(fù)上線,修改第3位
當(dāng)然,可以根據(jù)實(shí)際情況來設(shè)計(jì),比如項(xiàng)目特別大,可以使用四段表達(dá)Tag,項(xiàng)目比較小也可以使用二段式Tag,只要符合場景并有實(shí)際意義即可?!
提交信息格式:下面只是提供一種建議格式,大家可以根據(jù)自己的項(xiàng)目實(shí)際情況來定格式,只要能把當(dāng)前提交表達(dá)清楚,格式統(tǒng)一,方便快速閱讀和定位即可!
1.建議中文示例:
<新功能>(urllAnalyz) 添加解析url功能l
<修改>(TestServiceImpl) 修改某功能的某個實(shí)現(xiàn)為另一個實(shí)現(xiàn)
(TestUnti) 修復(fù)url特殊情況下解析失敗問題 (issue#12) <重構(gòu)>(getData) 重構(gòu)獲取數(shù)據(jù)的方法
<測試>(getDataTest) 添加(修改、刪除)獲取數(shù)據(jù)的單元測試代碼
<文檔>(doc)修改(添加、刪除)文檔
2.建議的英文示例:
feat:新功能(feature)
style:格式
fix:修補(bǔ)bug
refactor:重構(gòu)
test:測試相關(guān)
docs:文檔(documentation)
3.格式(type:scope:body:issue)?:<|新功能|修改|Bug修復(fù)|重構(gòu)|測試>(影響模塊)提交描述信息(#issue?)
4.優(yōu)點(diǎn):
與github數(shù)據(jù)issue關(guān)聯(lián),便于通過issue獲取更多信息
commit 提交時(shí),格式統(tǒng)一,便于后續(xù)快速準(zhǔn)確定位提交
可以更好的將此次提交表述清楚
四:Git操作過程
4.1 初始化項(xiàng)目,并上傳到git服務(wù)器
基本過程:創(chuàng)建遠(yuǎn)程倉庫、初始化本地git倉庫、將本地倉庫與遠(yuǎn)程倉庫關(guān)聯(lián)起來、添加本地倉庫想要提交的代碼到本地git緩沖區(qū),將本地倉庫的本地分支與遠(yuǎn)程倉庫的遠(yuǎn)程分支關(guān)聯(lián)起來、提交代碼
在git服務(wù)器上創(chuàng)建同名git項(xiàng)目,并獲取http地址
本地git初始化項(xiàng)目git倉庫,在項(xiàng)目目錄下
git init將本地git倉庫和遠(yuǎn)程倉庫關(guān)聯(lián)起來,并設(shè)置遠(yuǎn)程倉庫名稱
git remote add
其中http地址為上述第一步獲取的遠(yuǎn)程倉庫的地址,name一般為origin,當(dāng)然也可以設(shè)置其他的名字 例如:git remote add origin http://igit.corp.com/my/test.git
? ? 4. 添加項(xiàng)目文件到本地git緩沖區(qū) git add-A git commit-m '初始化項(xiàng)目'
或者 git commit-a-m '初始化項(xiàng)目'
? ? 5. 將本地分支關(guān)聯(lián)遠(yuǎn)程分支并提交,git默認(rèn)在遠(yuǎn)程分支上創(chuàng)建于本地分支同名的分支 git push--set-upstream origin master
這就是將本地的master分支 與 origin遠(yuǎn)程倉庫關(guān)聯(lián)起來并在遠(yuǎn)程倉庫創(chuàng)建同名master分支,以后本地master都提交到遠(yuǎn)程倉庫中的origin/master分支上。
upstream:上游的意思
至此,應(yīng)該就可以了,我們可以在git服務(wù)器上刷新看看是否提交上去了
4.2?提交某一分支的修改
查看當(dāng)前分支的修改?
git status查看想要查看的文件的修改?
git diff確認(rèn)正確后,提交修改到暫存區(qū)?
git add-A或者git add提交到本地倉庫?
git commit-m'提交信息'提交到遠(yuǎn)程倉庫?
git push
4.3?拉取遠(yuǎn)程分支修改到本地分支
當(dāng)遠(yuǎn)程分支別人推了一版新的代碼時(shí),我們想要將代碼拉下來,可以采用兩種方式pull 和 fetch+merge:(他們的不同點(diǎn)文章上面已經(jīng)解釋)
使用pull:
將遠(yuǎn)程分支最新代碼更新合并到本地倉庫區(qū)和工作區(qū)?
git pull
使用fetch:
將遠(yuǎn)程所有分支最新的commitid更新到FETCHHEAD,記錄遠(yuǎn)程分支最新的commit_id 和 本地倉庫區(qū)?
git fetch將最新的代碼合并到工作區(qū)?
git merge
4.4?取消track某一文件
git rm-r--cache
untrack后,使用commit -a 時(shí),不會將其添加到暫存區(qū)中
之后會在.ignore文件中將該untrack的文件添加進(jìn)去,完成
4.5?保存賬號密碼,避免每次push都要輸入(簡單方法)
確保在git中手動輸入過賬號和密碼
輸入下面語句即可?
git config--globalcredential.helper store
4.6?暫存自己的修改,便于接著工作(特別有用)
試想一個場景:如果你正在一個分支上工作修改,leader讓你改另外的分支的BUG或者對其他的分支做一些操作。
我們知道如果一個分支上有還沒有commit的修改的話,不可以切換分支,但是又因?yàn)樽约旱墓ぷ鬟€未完成,不想commit,此時(shí) git stash 就起作用了。
你要把現(xiàn)在正在工作的分支保存下來,等處理完其他的再回來接著當(dāng)前分支的修改工作。
? ? 1. 將當(dāng)前分支的修改暫存起來(此處不等于add+commit)?git stash
備份當(dāng)前的工作區(qū)的內(nèi)容,從最新的一次提交中讀取相關(guān)內(nèi)容,讓工作區(qū)保證和上次提交的內(nèi)容一致。同時(shí),將當(dāng)前的工作區(qū)修改的內(nèi)容保存到Git棧中暫存起來。
? ? 2. 切換到別的分支工作,完成后切換回原來的工作分支,查看暫存列表?git stash list
顯示Git棧內(nèi)的所有備份,可以利用這個列表來決定從那個地方恢復(fù)
? ? 3. 恢復(fù)暫存的修改到工作區(qū)?git stash apply?恢復(fù)暫存之后不刪除暫存
從Git棧中讀取最新一次保存的內(nèi)容,恢復(fù)工作區(qū)的相關(guān)內(nèi)容。
? ? git stash pop 恢復(fù)暫存之后刪除暫存
從Git棧中讀取最新一次保存的內(nèi)容,恢復(fù)工作區(qū)的相關(guān)內(nèi)容。之后pop會刪除最新的暫存。
? ? 4. 刪除“暫存”?git stash drop
從Git棧刪除最舊的一個暫存
結(jié)束
4.7?將文件修改回退到某一狀態(tài)
一些已經(jīng)提交的或者已經(jīng)修改的部分,想要再修改一下,或者刪除已經(jīng)提交的
a. 刪除某些commit,將head重定位到某一commit(回溯到以前的版本) git reset--hard?
注意!!!上述命令會將commit_id前的所有commit修改刪除git reset?
上述命令不會將commit_id前的commit刪除,而是會將修改回退到本地工作區(qū)?
git push origin HEAD--force 此步驟將服務(wù)器方也設(shè)置為相應(yīng)的commit
b. 將文件修改恢復(fù)到當(dāng)前已提交分支的原樣(未 git add 情況下) 撤銷修改就回到和版本庫一模一樣的狀態(tài),即用版本庫里的版本替換工作區(qū)的版本
git checkout--
c. 將文件修改恢復(fù)到當(dāng)前已提交分支的原樣(已經(jīng) git add 情況下)?
git reset HEAD 將add退回?
git checkout--
d. 將文件修改恢復(fù)到已提交分支的原樣(已經(jīng) git commit 情況下)?
git reset 此處commit_id可以是任意分支的commit_id?
git checkout--
4.8?版本的回溯與前進(jìn)
有時(shí)候需要回溯或前進(jìn)到以前的版本 或 回溯前進(jìn)到以前的commit
只要記住commit_id就可以在版本之間來回的穿梭,注意是可以“來回”穿梭哦
獲取需要回溯到版本的commitid?
git log?--> 復(fù)制所需的版本commitid回退到該版本?
git reset--hard如果想讓服務(wù)器也回退到該版本的話?
git push origin HEAD--force
更多文章,請關(guān)注“匠心Java”公眾號!
五:Git常用命令
初始化項(xiàng)目為git項(xiàng)目?
git init
clone服務(wù)器代碼到本地?
git clone
添加修改文件到暫存區(qū)?
git add?
git add-A 添加所有修改文件到暫存區(qū)
提交修改到本地倉庫?
git commit-m'提交信息'?
git commit-a-m'提交信息' 相當(dāng)于git add -A + git commit -m 的整合
提交本地倉庫的修改到遠(yuǎn)程倉庫?
git push
將遠(yuǎn)程庫
git push--set-upstream
查看文件本次的修改?
git diff 顯示本次所有被修改文件的修改?
git diff 顯示該文件本次的修改
查看當(dāng)前分支下當(dāng)前狀態(tài)?
git status 顯示出被修改的文件和提交的次數(shù)等
查看提交歷史?
git log?
git log--graph 查看分支合并圖
merge其他分支到當(dāng)前分支?
git merge
在merge過程如果出現(xiàn)沖突,在解決沖突后會產(chǎn)生一個新的commit,并且HEAD指向該commit 如果沒有沖突,HEAD會在分支的最新commit上
切換到上一個分支?
git checkout-
切換到其他分支?
git checkout
在某一分支基礎(chǔ)上創(chuàng)建新分支?
git checkout 切換到基礎(chǔ)分支
git checkout-b 在當(dāng)前分支基礎(chǔ)上 創(chuàng)建新分支
顯示分支?
git branch 所有本地分支?
git branch-r 所有遠(yuǎn)程分支?
git branch-a 所有分支,本地和遠(yuǎn)程
刪除本地分支?
git branch-D
刪除遠(yuǎn)程分支?
git push origin--delete
添加一個新的遠(yuǎn)程倉庫?
git remote add
在同一個項(xiàng)目的git url中可以添加多個遠(yuǎn)程倉庫 每個倉庫相互隔離有自己的分支管理
將本地分支與遠(yuǎn)程倉庫中分支聯(lián)系起來?
git push--set-upstream<遠(yuǎn)程倉庫名稱><遠(yuǎn)程倉庫中分支名稱>
以后本地的該分支的push,會默認(rèn)提交到設(shè)置的遠(yuǎn)程倉庫中遠(yuǎn)程分支中
刪除遠(yuǎn)程倉庫 git remote rm<遠(yuǎn)程倉庫name>
刪除本地tag git tag-d
刪除遠(yuǎn)程tag git push origin:refs/tags/
查看tag信息 git show
暫存當(dāng)前修改 git stash
查看暫存列表 git stash lsit
恢復(fù)暫存的修改?
git stash apply (恢復(fù)后不刪除暫存)?
git stash pop (恢復(fù)后刪除暫存)
刪除暫存 git stash drop
撤回已經(jīng)add到暫存區(qū)的文件到本地工作區(qū)?
git reset HEAD?
git reset HEAD 回退所有add
add會被標(biāo)識為Changes to be committed,取消add后標(biāo)識為Changes not staged for commit(不等于untrack)
取消track某一文件 git rm-r--cache
untrack后,使用commit -a 時(shí),不會將其添加到暫存區(qū)中
只merge某一個分支上的某一個commit git cherry-pick<被merge分支中的某一個commit的commit-id>
撤銷在本地工作區(qū)的文件的修改
撤銷修改就回到和版本庫一模一樣的狀態(tài),即用版本庫里的版本替換工作區(qū)的版本 git checkout--
刪除某些commit,將head重定位到某一commit(回溯到以前的版本)?
git reset--hard?
git push origin HEAD--force 此步驟將服務(wù)器方也設(shè)置為相應(yīng)的commit
刪除本地在遠(yuǎn)程服務(wù)器上不存在的分支 git remote prune origin
拉取遠(yuǎn)程分支到本地 git fetch origin
新建一個tag到指定commit?
git tag git tag 當(dāng)前commit
取消當(dāng)前合并,重建合并前狀態(tài) git merge--abort
總結(jié)
本文介紹了Git是什么、Git的存儲結(jié)構(gòu)、Git的提交規(guī)則和一些工作中常會用到的git操作的過程,最后總結(jié)了常用的命令。Git在工作中的團(tuán)隊(duì)開發(fā)中起著至關(guān)重要的作用,希望本篇文章可以對大家有些許幫助~


近期精彩內(nèi)容推薦:??
?魂斗羅只有128KB為何可以實(shí)現(xiàn)那么長的劇情

