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