目錄
- Git起源
- 基本概念
- Branch、HEAD和Commit tree
- Git分支
- git merge 和 git rebase 的區別和抉擇
- 與遠程倉庫的互動
- 關于一些實際開發場景的問題和解決方式
前言:本文主要介紹git的原理、使用和一些技巧,目的在于使讀者對git的了解不僅僅局限于簡單的使用push、pull命令,而要做到知其然且知其所以然,當然,本文并不會深入去探討諸如git的實作原理之類的深層次東西,畢竟它只是一個代碼管理工具罷了,作為使用者,我們只要達到真正熟練使用的地步就夠了,至于更深層次的東西,諸位有興趣的可以自行學習研究,
另外,本文分支相關圖片取自learngitbranching,這是個用游戲的方式,圖文結合學習git分支的網站,相當nice,推薦大家去完整過一遍,相信對于git的理解會更上一層樓,
Git起源
git是由Linux的作者Linus花兩周時間寫出的分布式版本控制軟體,在這之前,Linux社區使用BitKeeper作為版本控制系統,但是由于社區中有人試圖破解BitKeeper的協議,這惹惱了BitKeeper的東家BitMover公司,于是BitMover決定識訓linux社區的免費使用權,
在這樣的背景下,Linus花了兩周時間寫出了git,在一個月內替換了BitKeeper,作為Linux的版本控制工具,并在后面不斷完善,最終成為了現在代碼版本控制的首選
基本概念
三種作業域:
- git目錄(git direcdtory):即倉庫(Repository),保存專案中所有版本和相關資訊,是git存放資料和資訊的地方
- 作業目錄(work directory): 是對應專案的某個版本的檔案集合,對應從 git 目錄中解壓出來的供用戶進行操作和修改的資料和資訊
- 暫存目錄(staging area):用于記錄下次commit時需要保存的檔案串列
三種檔案狀態:
- committed:已提交狀態,表示資料檔案已經被保存至本地資料倉庫中,
- modified:修改狀態,表示檔案已被修改,但是尚未被提交(保存),
- staged:暫存狀態,表示是被標記了的被修改檔案,在下次提交時會將所有標記過的修改保存,
另外新增的檔案為untracked file,未在git管理范圍內,需要先通過git add添加到暫存目錄,然后其狀態會變為staged

如圖所示,git分為遠端和本地,遠程遠程服務器存盤了倉庫資訊,而本地則是三種作業域都有,
Branch、HEAD和Commit tree
本地提交代碼到遠端的一般流程:
- git add,將修改保存到暫存區(stage area)
- git commit,將暫存區中的檔案推送到本地分支,本地倉庫更新
- git push,將本地倉庫的更改推送到遠程倉庫,遠程倉庫更新
可以看到,想要更新代碼,commit是必不可少的,每次commit都會生成一個作業目錄的快照(前提是有修改),在git中,這些commit的快照資料使用樹(tree)結構來管理,稱為提交樹(Commit Tree)或者作業樹(Work Tree),
Git 的分支(Branch),其實本質上僅僅是指向提交物件的可變指標,分支是git的核心所在,因為分支的存在,作業樹才是作業樹而不是作業"線",可以將每個分支看作作業樹的分叉,專案可以在不同分支上并行開發,然后在合適的時機又可以合并在一起,這都是分支的作用,
HEAD表示當前所處提交位置,通常來說,HEAD是指向某個分支的,當然也可以手動切換將HEAD指向作業樹中的任意commit(這種情況稱為HEAD分離),

圖中一共有c0-c4四個提交,main、bugFix和feature三個分支,三個分支分別指向C1、C3、C4三個提交,HEAD處于分離狀態,指向C2
了解了以上的基礎概念以后,讓我們來探討一下git分支相關內容,
Git分支
之前說了,分支的存在是為了并行開發,每一個分支都會指向一個具體的提交,需要多人協作的專案離不開對分支的操作,
通常來說,新建一個專案時默認分支為master,可以根據需要新建develop、release等分支,
下面介紹一些常見的git分支相關命令
- git commit,以當前提交為父節點生成新的子提交節點,并且當前HEAD/Branch會指向新生成的節點
- git branch,單獨使用時查看所有分支,后面加一個branchName表示在當前節點創建名為branchName的新分支,git checkout -b branchName也能達到相同的效果,區別在于后者會將HEAD指向新創建的分支
- git checkout BRANCH/COMMIT,切換到對應的分支或者提交節點,之前有提過,直接切換到提交節點就是HEAD分離狀態
- git merge BRANCH/COMMIT,將當前提交節點和指定提交節點合并并生成新的提交節點,新生成的節點有兩個父節點,
- git rebase BRANCH/COMMIT,將當前分支所在節點及之前的節點中有且在另一分支/節點中所沒有的節點全部按序復制一份到目標分支,然后將當前BRANCH/HEAD移到目標位置,
- git reset COMMIT.撤銷commit到指定提交,與git branch -f CURRENT_COMMIT COMMIT效果是一樣的,但是這種更改只能在本地體現,是不能同步到遠程的
- git revert COMMIT,要想撤銷能同步到遠程,就得用到git revert COMMIT,此命令會通過新生成提交節點的方式撤銷指定的提交節點
- git cherry-pick COMMIT_1 COMMIT_2 ... ,選取指定的一些節點按序rebase到當前分支
git merge 和 git rebase 的區別和抉擇
git rebase:
- 優點:提交樹呈線性,干凈簡單
- 缺點:修改了提交樹的歷史
git merge:
- 優點:提交記錄順序正確,不會造成迷惑
- 缺點:多分支時顯得看起來很復雜
兩者如何抉擇,該使用哪條命令來合并,這取決于用戶的習慣,如果對提交歷史順序的正確性有要求,就用git merge,否則使用git rebase
與遠程倉庫的互動
通常來說,開發的一般流程是在遠程建立一個倉庫,然后開發人員各自在本地clone倉庫,新建自己的分支進行開發,開發完成后再推送到遠程分支,再合并到主分支,
當我們clone遠程倉庫到本地時,會在本地復制一份倉庫資訊和作業目錄

注意,本地多了一個origin/main的分支,這個分支叫做遠程分支,它反映了你最近一次操作遠程倉庫的狀態,遠程分支比較特殊,不能像普通分支一樣通過checkout、branch等命令直接操控,必須通過pull、push、fetch等命令與遠端同步,
下面介紹一些常見的與遠程倉庫互動的命令:
- git clone Repository,將遠程倉庫克隆到本地,可通過git clone -b branchName Repository命令指定克隆的分支,
- git fetch,下載遠程分支的最新狀態到本地,只會更新本地的遠程分支,不會更改HEAD和本地分支遠程
有更新

使用 git fetch后

- git pull,可以視作 git fetch + git merge 的縮寫,存在下列常見情況,遠程分支有人提交了更新,自己本地也提交了更新,這時候就需要先拉取最新的代碼
使用git pull,第一步是下載最新分支更改,即git fetch

- git push,將當前分支的本地更改推送到遠程分支,git push會更新本地的遠程分支,并且將修改同步到遠端對應的分支

使用git push推送

關于一些實際開發場景的問題和解決方式
前提:團隊目前使用develop分支作為本地測驗環境,Release分支作為代碼備份,通過手動部署的方式部署到真實環境,也就是說,每次開發完成以后會將develop分支合到release分支,
問題:在某次開發后develop最新提交為C2,但是C2忘了合并到release分支,然后又另外創建了個分支nas開發nas相關功能C3,現在nas已經合并到develop分支,這時候nas相關功能由于存在一些問題,需要回滾,請問這時候應該怎么做?

解決方案:使用git revert C3回滾

在回滾以后另外新建分支開發新功能C4,之后又想將nas分支的功能重新合并到develop,應該怎么做?

解決方案: git revert C3'

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/466058.html
標籤:其他
