吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

通俗易懂的Git各指令的本質

數據分析與開發 ? 來源:掘金 ? 作者: Bezier ? 2021-06-24 18:06 ? 次閱讀

0前言

作為當前世界上最強大的代碼管理工具Git相信大家都很熟悉,但據我所知有很大一批人停留在clone、commit、pull、push.。。的階段,是不是對rebase心里沒底只敢用merge?

碰見版本回退就抓瞎?別問我怎么知道的,問就是:“我曾經就是這樣啊~~”。

針對這些問題,今天我就將這幾年對Git的認知和理解分享出來,盡可能的從本質去講解Git,幫助你一步一步去了解Git的底層原理,相信讀完本篇文章你便可以換種姿態,更加風騷得使用Git各種指令。

1基本概念

1.1 Git的優勢

Git是一個分布式代碼管理工具,在討論分布式之前避免不了提及一下什么是中央式代碼管理倉庫

中央式:所有的代碼保存在中央服務器,所以提交必須依賴網絡,并且每次提交都會帶入到中央倉庫,如果是協同開發可能頻繁觸發代碼合并,進而增加提交的成本和代價。最典型的就是svn

分布式:可以在本地提交,不需要依賴網絡,并且會將每次提交自動備份到本地。每個開發者都可以把遠程倉庫clone一份到本地,并會把提交歷史一并拿過來。代表就是Git

那Git相比于svn有什么優勢呢?

打個比方:“巴拉巴拉寫了一大堆代碼,突然發現寫的有問題,我想回到一個小時之前”,對于這種情況Git的優勢就很明顯了,因為commit的成本比較小并且本地會保存所有的提交記錄,隨時隨刻可以進行回退。

在這并不是說svn的不能完成這種操作,只是Git的回退會顯得更加的優雅。Git相比于中央式工具還有很多優點,就不一一列舉了,感興趣的可自行了解。

1.2 文件狀態

在Git中文件大概分為三種狀態:已修改(modified)、已暫存(staged)、已提交(committed)

修改:Git可以感知到工作目錄中哪些文件被修改了,然后把修改的文件加入到modified區域

暫存:通過add命令將工作目錄中修改的文件提交到暫存區,等候被commit

提交:將暫存區文件commit至Git目錄中永久保存

1.3 commit節點

為了便于表述,本篇文章我會通過節點代稱commit提交

在Git中每次提交都會生成一個節點,而每個節點都會有一個哈希值作為唯一標示,多次提交會形成一個線性節點鏈(不考慮merge的情況)。

節點上方是通過 SHA1計算的哈希值

C2節點包含C1提交內容,同樣C3節點包含C1、C2提交內容

1.4 HEAD

HEAD是Git中非常重要的一個概念,你可以稱它為指針或者引用,它可以指向任意一個節點,并且指向的節點始終為當前工作目錄,換句話說就是當前工作目錄(也就是你所看到的代碼)就是HEAD指向的節點。

還以圖1-1舉例,如果HEAD指向C2那工作目錄對應的就是C2節點。具體如何移動HEAD指向后面會講到,此處不要糾結。

同時HEAD也可以指向一個分支,間接指向分支所指向的節點。

1.5 遠程倉庫

雖然Git會把代碼以及歷史保存在本地,但最終還是要提交到服務器上的遠程倉庫。通過clone命令可以把遠程倉庫的代碼下載到本地,同時也會將提交歷史、分支、HEAD等狀態一并同步到本地,但這些狀態并不會實時更新,需要手動從遠程倉庫去拉取,至于何時拉、怎么拉后面章節會講到。

通過遠程倉庫為中介,你可以和你的同事進行協同開發,開發完新功能后可以申請提交至遠程倉庫,同時也可以從遠程倉庫拉取你同事的代碼。

注意點

因為你和你的同事都會以遠程倉庫的代碼為基準,所以要時刻保證遠程倉庫的代碼質量,切記不要將未經檢驗測試的代碼提交至遠程倉庫

2分支

2.1 什么是分支?

分支也是Git中相當重要的一個概念,當一個分支指向一個節點時,當前節點的內容即是該分支的內容,它的概念和HEAD非常接近同樣也可以視為指針或引用,不同的是分支可以存在多個,而HEAD只有一個。通常會根據功能或版本建立不同的分支。

那分支有什么用呢?

舉個例子:你們的 App 經歷了千辛萬苦終于發布了v1.0版本,由于需求緊急v1.0上線之后便馬不停蹄的開始v1.1,正當你開發的興起時,QA同學說用戶反饋了一些bug,需要修復然后重新發版,修復v1.0肯定要基于v1.0的代碼,可是你已經開發了一部分v1.1了,此時怎么搞?

面對上面的問題通過引入分支概念便可優雅的解決。

先看左邊示意圖,假設C2節點既是v1.0版本代碼,上線后在C2的基礎上新建一個分支ft-1.0

再看右邊示意圖,在v1.0上線后可在master分支開發v1.1內容,收到QA同學反饋后提交v1.1代碼生成節點C3,隨后切換到ft-1.0分支做bug修復,修復完成后提交代碼生成節點C4,然后再切換到master分支并合并ft-1.0分支,到此我們就解決了上面提出的問題

除此之外利用分支還可以做很多事情,比如現在有一個需求不確定要不要上線,但是得先做,此時可以單獨創建一個分支開發該功能,等到啥時候需要上線直接合并到主分支即可。分支適用的場景很多就不一一列舉了。

注意點

當在某個節點創建一個分支后,并不會把該節點對應的代碼復制一份出來,只是將新分支指向該節點,因此可以很大程度減少空間上的開銷。一定要記著不管是HEAD還是分支它們都只是引用而已,量級非常輕

3命令詳解

3.1 提交相關

前面我們提到過,想要對代碼進行提交必須得先加入到暫存區,Git中是通過命令 add 實現

添加某個文件到暫存區:

git add 文件路徑

添加所有文件到暫存區:

git add 。

同時Git也提供了撤銷工作區和暫存區命令

撤銷工作區改動:

git checkout -- 文件名

清空暫存區:

git reset HEAD 文件名

提交:

將改動文件加入到暫存區后就可以進行提交了,提交后會生成一個新的提交節點,具體命令如下:

git commit -m “該節點的描述信息

3.2 分支相關

創建分支

創建一個分支后該分支會與HEAD指向同一節點,說通俗點就是HEAD指向哪創建的新分支就指向哪,命令如下:

git branch 分支名

切換分支

當切換分支后,默認情況下HEAD會指向當前分支,即HEAD間接指向當前分支指向的節點

git checkout 分支名

同時也可以創建一個分支后立即切換,命令如下:

git checkout -b 分支名

刪除分支

為了保證倉庫分支的簡潔,當某個分支完成了它的使命后應該被刪除。比如前面所說的單獨開一個分支完成某個功能,當這個功能被合并到主分支后應該將這個分支及時刪除。

刪除命令如下:

git branch -d 分支名

3.3 合并相關

關于合并的命令是最難掌握同時也是最重要的。我們常用的合并命令大概有三個merge、rebase、cherry-pick

merge

merge是最常用的合并命令,它可以將某個分支或者某個節點的代碼合并至當前分支。具體命令如下:

git merge 分支名/節點哈希值

如果需要合并的分支完全領先于當前分支。

由于分支ft-1完全領先分支ft-2即ft-1完全包含ft-2,所以ft-2執行了“git merge ft-1”后會觸發fast forward(快速合并),此時兩個分支指向同一節點,這是最理想的狀態。

這種情況就不能直接合了,當ft-2執行了“git merge ft-1”后Git會將節點C3、C4合并隨后生成一個新節點C5,最后將ft-2指向C5 如圖3-2(右)

注意點:

如果C3、C4同時修改了同一個文件中的同一句代碼,這個時候合并會出錯,因為Git不知道該以哪個節點為標準,所以這個時候需要我們自己手動合并代碼

rebase

rebase也是一種合并指令,命令行如下:

git rebase 分支名/節點哈希值

與merge不同的是rebase合并看起來不會產生新的節點(實際上是會產生的,只是做了一次復制),而是將需要合并的節點直接累加。

ft-1.0執行了git rebase master后會將C4節點復制一份到C3后面,也就是C4‘,C4與C4’相對應,但是哈希值卻不一樣。

rebase相比于merge提交歷史更加線性、干凈,使并行的開發流程看起來像串行,更符合我們的直覺。既然rebase這么好用是不是可以拋棄merge了?其實也不是了,下面我羅列一些merge和rebase的優缺點:

merge優缺點:

優點:每個節點都是嚴格按照時間排列。當合并發生沖突時,只需要解決兩個分支所指向的節點的沖突即可

缺點:合并兩個分支時大概率會生成新的節點并分叉,久而久之提交歷史會變成一團亂麻

rebase優缺點:

優點:會使提交歷史看起來更加線性、干凈

缺點:雖然提交看起來像是線性的,但并不是真正的按時間排序,比如圖3-3中,不管C4早于或者晚于C3提交它最終都會放在C3后面。并且當合并發生沖突時,理論上來講有幾個節點rebase到目標分支就可能處理幾次沖突

對于網絡上一些只用rebase的觀點,作者表示不太認同,如果不同分支的合并使用rebase可能需要重復解決沖突,這樣就得不償失了。但如果是本地推到遠程并對應的是同一條分支可以優先考慮rebase。所以我的觀點是 根據不同場景合理搭配使用merge和rebase,如果覺得都行那優先使用rebase

cherry-pick

cherry-pick的合并不同于merge和rebase,它可以選擇某幾個節點進行合并,如圖3-4

命令行:

git cherry-pick 節點哈希值

假設當前分支是master,執行了git cherry-pick C3(哈希值),C4(哈希值)命令后會直接將C3、C4節點抓過來放在后面,對應C3‘和C4’

3.4 回退相關

分離HEAD

在默認情況下HEAD是指向分支的,但也可以將HEAD從分支上取下來直接指向某個節點,此過程就是分離HEAD,具體命令如下:

git checkout 節點哈希值

//也可以直接脫離分支指向當前節點

git checkout --detach

由于哈希值是一串很長很長的亂碼,在實際操作中使用哈希值分離HEAD很麻煩,所以Git也提供了HEAD基于某一特殊位置(分支/HEAD)直接指向前一個或前N個節點的命令,也即相對引用,如下:

//HEAD分離并指向前一個節點

git checkout 分支名/HEAD^

//HEAD分離并指向前N個節點

git checkout 分支名~N

將HEAD分離出來指向節點有什么用呢?舉個例子:如果開發過程發現之前的提交有問題,此時可以將HEAD指向對應的節點,修改完畢后再提交,此時你肯定不希望再生成一個新的節點,而你只需在提交時加上--amend即可,具體命令如下:

git commit --amend

回退

回退場景在平時開發中還是比較常見的,比如你巴拉巴拉寫了一大堆代碼然后提交,后面發現寫的有問題,于是你想將代碼回到前一個提交,這種場景可以通過reset解決,具體命令如下:

//回退N個提交

git reset HEAD~N

reset和相對引用很像,區別是reset會使分支和HEAD一并回退。

3.5 遠程相關

當我們接觸一個新項目時,第一件事情肯定是要把它的代碼拿下來,在Git中可以通過clone從遠程倉庫復制一份代碼到本地,具體命令如下:

git clone 倉庫地址

前面的章節我也有提到過,clone不僅僅是復制代碼,它還會把遠程倉庫的引用(分支/HEAD)一并取下保存在本地,如圖3-5所示:

其中origin/master和origin/ft-1為遠程倉庫的分支,而遠程的這些引用狀態是不會實時更新到本地的,比如遠程倉庫origin/master分支增加了一次提交,此時本地是感知不到的,所以本地的origin/master分支依舊指向C4節點。我們可以通過fetch命令來手動更新遠程倉庫狀態

小提示:

并不是存在服務器上的才能稱作是遠程倉庫,你也可以clone本地倉庫作為遠程,當然實際開發中我們不可能把本地倉庫當作公有倉庫,說這個只是單純的幫助你更清晰的理解分布式

fetch

說的通俗一點,fetch命令就是一次下載操作,它會將遠程新增加的節點以及引用(分支/HEAD)的狀態下載到本地,具體命令如下:

git fetch 遠程倉庫地址/分支名

pull

pull命令可以從遠程倉庫的某個引用拉取代碼,具體命令如下:

git pull 遠程分支名

其實pull的本質就是fetch+merge,首先更新遠程倉庫所有狀態到本地,隨后再進行合并。合并完成后本地分支會指向最新節點

另外pull命令也可以通過rebase進行合并,具體命令如下:

git pull --rebase 遠程分支名

push

push命令可以將本地提交推送至遠程,具體命令如下:

git push 遠程分支名

如果直接push可能會失敗,因為可能存在沖突,所以在push之前往往會先pull一下,如果存在沖突本地解決。push成功后本地的遠程分支引用會更新,與本地分支指向同一節點。

綜上所述

不管是HEAD還是分支,它們都只是引用而已,引用+節點是 Git 構成分布式的關鍵

merge相比于rebase有更明確的時間歷史,而rebase會使提交更加線性應當優先使用

通過移動HEAD可以查看每個提交對應的代碼

clone或fetch都會將遠程倉庫的所有提交、引用保存在本地一份

pull的本質其實就是fetch+merge,也可以加入--rebase通過rebase方式合并

作者:掘金-Bezier

鏈接:https://juejin.cn/post/6895246702614806542

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4825

    瀏覽量

    69046
  • SHA
    SHA
    +關注

    關注

    0

    文章

    16

    瀏覽量

    8458
  • Git
    Git
    +關注

    關注

    0

    文章

    201

    瀏覽量

    15818

原文標題:Git 各指令的本質,真是通俗易懂啊

文章出處:【微信號:DBDevs,微信公眾號:數據分析與開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    飛凌嵌入式ElfBoard ELF 1板卡-git管理源碼之git安裝和使用

    :~/work/example/hello$ git add hello.c(4)提交版本提交暫存區域的所有修改到本地倉庫(如果修改文件后未添加到暫存區,將不會被提交),用git status指令(在分支內
    發表于 01-14 09:08

    請問什么是軌到軌?這種運放和普通運放比有什么特點和優點?

    什么是軌到軌?這種運放和普通運放比有什么特點和優點? 最近看到TI有一些運放屬于軌到軌,不知道這類有什么特點,與普通的比有什么優缺點沒?哪位給講的通俗易懂點啊?
    發表于 09-18 06:52

    【「倉頡編程快速上手」閱讀體驗】+初步讀后感

    ,內容易讀是這本書的一大亮點。作者運用簡潔明了的語言,將復雜的概念和理論闡述得通俗易懂。沒有過多的專業術語堆砌,即使是沒有相關背景知識的讀者也能輕松理解。書中的案例豐富且貼近生活,進一步增強了內容
    發表于 09-10 11:09

    通俗易懂的理解,什么是芯片?

    我們在日常工作和生活中,經常會使用到各種各樣的電子或電器產品,例如電腦、手機、電視、冰箱、洗衣機等。 這些產品,如果我們把它拆開,都會看到類似下面這樣的一塊綠色板子。 大家都知道,這個綠色板子,叫做電路板。更官方一點的名稱,叫印制電路板,也就是PCB(Printed Circuit Board,國外有時候也叫PWB,Printed Wire Board)。 在PCB上,焊接了很多的電子元器件,例如電容、電阻、電感等。 我們還可以看到,有一些黑色的方形元件。 沒錯,這個
    的頭像 發表于 08-22 13:32 ?3.9w次閱讀
    <b class='flag-5'>通俗易懂</b>的理解,什么是芯片?

    ubuntu下的vscode插件安裝idf時,總是找不到git,為什么?

    總是提示:Git is not found in current environment 但是我已經在setting.json下設置了\"git.path\": \"/bin/git\" 同行,命令行里查看
    發表于 06-21 07:16

    Git發布新版本 修補五處安全漏洞 包含嚴重遠程代碼執行風險

    CVE-2024-32002漏洞的嚴重性在于,黑客可通過創建特定的Git倉庫子模塊,誘騙Git將文件寫入.git/目錄,而非子模塊的工作樹。如此一來,攻擊者便能在克隆過程中植入惡意腳本,用戶幾乎無法察覺。
    的頭像 發表于 05-31 10:09 ?654次閱讀

    CKS32F107xx系列時鐘組成介紹

    作為MCU運行的基礎,時鐘是MCU各個模塊工作時序的最小時間單位,推動MCU的各指令執行,是MCU選型的一個重要指標。
    的頭像 發表于 05-20 14:04 ?507次閱讀
    CKS32F107xx系列時鐘組成介紹

    【大語言模型:原理與工程實踐】探索《大語言模型原理與工程實踐》2.0

    讀者更好地把握大語言模型的應用場景和潛在價值。盡管涉及復雜的技術內容,作者盡力以通俗易懂的語言解釋概念,使得非專業背景的讀者也能夠跟上節奏。圖表和示例的運用進一步增強了書籍的可讀性。本書適合對人工智能
    發表于 05-07 10:30

    FPGA與ARM的本質區別

    FPGA(Field-Programmable Gate Array)與ARM在多個方面存在本質區別。 首先,從它們的定義和結構上來看,FPGA是一種現場可編程門陣列,屬于可編程器件的一種。它的內部
    發表于 04-28 09:00

    FPGA與ARM的本質區別是什么?

    FPGA(Field-Programmable Gate Array)與ARM在多個方面存在本質區別。 首先,從它們的定義和結構上來看,FPGA是一種現場可編程門陣列,屬于可編程器件的一種。它的內部
    發表于 04-28 08:56

    發酵罐攪拌器軸磨損修復方法

    這樣修復發酵罐攪拌器軸磨損通俗易懂
    發表于 04-24 18:43 ?0次下載

    真的通俗易懂!差分信號電路的解讀

    一、什么是差分運放電路差分電路是具有對共模信號抑制,對差模信號放大特征的電路。該電路的兩個信號輸信號的差值是該電路的有效值。將這兩信號輸入只差進行放大后輸出。如果存在干擾信號,會對兩個輸入信號產生相同的干擾,通過二者之差,干擾信號的有效輸入為零,這就達到了抗共模干擾的目的。對于運算放大電路來說,運放工作在線性區,所以電路一定是負反饋電路。運放的基本分析方法就
    的頭像 發表于 04-24 08:10 ?7329次閱讀
    真的<b class='flag-5'>通俗易懂</b>!差分信號電路的解讀

    詳解4種過壓保護電路!電源保護,通俗易懂

    今天給大家分享的是:過壓保護、過壓保護原理、過壓保護電路。 一、過壓保護是什么意思? 過壓保護是一種電源功能,當輸入電壓超過預設值時會切斷電源,為了防止高壓浪涌,通常會一些過壓保護方法。 大多數電源都使用過電壓保護電路來防止損壞電子元件。過電壓條件的影響因電路而異,范圍從損壞組件到降低組件性能并導致電路故障或火災。 由于電源內部故障或配電線路等外部原因,電源可能會出現過壓情況。 過電壓的幅度和持續時間是設
    的頭像 發表于 03-28 17:47 ?1.5w次閱讀
    詳解4種過壓保護電路!電源保護,<b class='flag-5'>通俗易懂</b>!

    飛凌ElfBoard ELF 1板卡-ubuntu18.04 git安裝及基本使用

    1.安裝gitsudo apt-get install git 2.git初始化git init 3.設置用戶名和郵箱git config --global user.name \"你
    發表于 03-21 16:23

    谷歌在Play商店啟用AI摘要功能?

    據悉,現階段該功能對少數用戶開放,他們可以在應用詳情頁面的“安裝”按鈕之下查看到“應用亮點”。這一功能依靠AI算法自動挖掘出應用的核心優勢,并用通俗易懂的文字概括出來,以便用戶能夠迅速了解應用的主要特色。
    的頭像 發表于 02-21 15:39 ?561次閱讀
    找真人百家乐官网的玩法技巧和规则 | 二八杠技巧| 1368棋牌游戏平台| 老虎机遥控器| 百家乐官网软件编辑原理| 百家乐官网云顶| 百家乐官网娱乐城| 百家乐心术| 全讯网信息| 马牌| 澳门百家乐官网怎么赢钱| 海王星百家乐官网的玩法技巧和规则| 属鸡与属羊做生意| 丽星百家乐的玩法技巧和规则 | 百家乐官网赌博技巧网| 联合百家乐官网的玩法技巧和规则 | 老牌百家乐官网娱乐城| 七胜百家乐官网娱乐网| 百家乐桌颜色可定制| 大发888信誉| 百家乐官网出千大全| 大丰收百家乐官网的玩法技巧和规则| 线上百家乐开户| 大发888海立方| 永利高百家乐官网开户| 鑫鑫百家乐官网的玩法技巧和规则 | 百家乐官网赌博器| 澳门百家乐规律星期娱乐城博彩| 大富豪棋牌游戏| 百家乐官网三路秘诀| 百家乐如何必胜| 大发888娱乐城加速器| 百家乐官网注码方法| rmb百家乐官网的玩法技巧和规则 木星百家乐官网的玩法技巧和规则 | 瑞丰国际开户| 网上赌百家乐官网的玩法技巧和规则 | 博彩百家乐官网画谜网| 聚众玩百家乐的玩法技巧和规则 | 百家乐官网香港六合彩| 百家乐对子的玩法| 神池县|