日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

git查看分支记录_git原理

發(fā)布時(shí)間:2024/9/30 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 git查看分支记录_git原理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

標(biāo)準(zhǔn)用法請(qǐng)參考git-scm。本文記錄筆者對(duì)git的一些理解,如有錯(cuò)誤,歡迎指正。
引用內(nèi)容已用markdown記號(hào)標(biāo)出。版權(quán)所有,轉(zhuǎn)載請(qǐng)注明出處。
文章完成中

這是引用內(nèi)容

First Edition:2021-01-27

文中的記號(hào)約定

<當(dāng)前分支>:用尖括號(hào)包裹,需要被替換

軟件環(huán)境

筆者將介紹 命令行,TortiseGit,VS中g(shù)it的使用

git學(xué)習(xí)指引

更適合把git當(dāng)作某種數(shù)據(jù)結(jié)構(gòu)來(lái)理解,從底層理解git

git中的一些概念

git分支并不是一個(gè)實(shí)體,而是一個(gè)指針,分支只存放了指向某個(gè)commit的指針,不保存其他信息。在master分支創(chuàng)建新提交后,分支指針指向?yàn)樾碌腸ommit。

HEAD表示當(dāng)前指向的位置,master/main一般用于主分支。不要混淆兩者概念

working-tree index lib
working-tree為工作目錄,即可以直接操作
index,也稱(chēng)stage,git commit將當(dāng)前index狀態(tài)保存,即git commit不處理工作目錄

git基本命令

  • add 添加文件到index
git add new.txt
  • commit 將當(dāng)前index提交到Local Repository
git commit -m "<這里是commit的注釋>" git commit -m "<這里是commit的注釋>" --allow-empty //使用此命令學(xué)習(xí)git分支 git commit -m "<這里是commit的注釋>" --allow-empty-message -m "" //允許空注釋
  • checkout 修改HEAD指針 底層修改 ./git/HEAD
git checkout <指定位置> //修改HEAD 指針到<指定位置>
  • switch 修改HEAD指針,使其指向某個(gè)分支而不是某個(gè)結(jié)點(diǎn)
git switch <分支> //切換到某個(gè)分支 //switch與checkout的區(qū)別: //checkout功能更加底層,修改HEAD指針的內(nèi)容,使其指向branch或者commit //switch只能指向分支
  • branch 創(chuàng)建分支
git branch new_branch //新建分支new_branch
  • reset 修改當(dāng)前分支的指針 底層修改文件 ./git/refs/head/<分支名>
git reset ad13f1 //修改當(dāng)前分支的指針 //git reset與checkout的區(qū)別 //git reset不修改HEAD指針,修改當(dāng)前分支指向的commit //git checkout修改HEAD指針

git指令

git rebase
git revert
git reset
git checkout
git merge
git cherry-pick

git merge命令
當(dāng)前工作再branch_master分支,此分支指向commitA,develop分支指向commitB,(AB字母僅供標(biāo)識(shí),沒(méi)有其他含義)。使用指令git merge develop,創(chuàng)建一個(gè)新的commitC,commitC以commitA和commitB為父結(jié)點(diǎn)。再次強(qiáng)調(diào),git的分支是一個(gè)指針,存放在./git/refs文件夾下。分支所包含的結(jié)點(diǎn)是以類(lèi)似鏈表的方式的進(jìn)行查找的,并不是線性記錄在某個(gè)文件中。
git中刪除分支并不會(huì)直接刪除commit object,不過(guò)分支指針丟失了,難以進(jìn)行查找,并且git有g(shù)c垃圾回收機(jī)制,會(huì)清理懸掛對(duì)象。(git誤操作后恢復(fù)數(shù)據(jù)原理,分支指針被清除,對(duì)象并未清除,而且在./git/logs文件夾內(nèi)有日志。) git fsck 命令驗(yàn)證數(shù)據(jù)庫(kù)中對(duì)象的連通性和有效性。
git revert命令
當(dāng)前master分支有commitA commitB commitC
使用git revert commitA命令生成commitD,commitD的父節(jié)點(diǎn)為commitC,commitD的內(nèi)容與A一致,但并不破壞歷史記錄.
注:git對(duì)象是以鏈表的形式組織。鏈表上的結(jié)點(diǎn)不能自由移動(dòng),但可以對(duì)讀取結(jié)點(diǎn)上的內(nèi)容,創(chuàng)建新結(jié)點(diǎn),這看起來(lái)像是回到了某次提交。
git reset命令
修改當(dāng)前分支指向的結(jié)點(diǎn)(分支指針總是指向該分支的最后一個(gè)結(jié)點(diǎn),或者說(shuō)分支指針記錄了該分支最后一個(gè)結(jié)點(diǎn),checkout命令是移動(dòng)HEAD指針)
當(dāng)前master分支有commitA commitB commitC
git reset commitA后,如果沒(méi)有分支線包含commitB,commitC,那么B、C不會(huì)顯示在git log中(因?yàn)間it log是動(dòng)態(tài)搜索),B、C可能會(huì)被清除。
注:git使用鏈接式的數(shù)據(jù)結(jié)構(gòu)。
git cherry-pick命令

git區(qū)域

這幾個(gè)區(qū)域是使用概念上的區(qū)別。
git Working-Tree 即工作文件夾
git index index區(qū)內(nèi)容,注意這里不是空的,使用git add 命令,將file1添加到object和index內(nèi)。
git commit區(qū)域 git commit將index內(nèi)容打包到tree obejct,建立commit object,修改當(dāng)前分支的指針,在logs文件夾內(nèi)寫(xiě)入HEAD和當(dāng)前分支的變更日志。
在git中,數(shù)據(jù)存放在以sha1為鍵名的數(shù)據(jù)庫(kù)中,以鏈表方式組織數(shù)據(jù)。這樣數(shù)據(jù)更加靈活。
git reflog是保存到本地的,不保存到遠(yuǎn)程。git log是動(dòng)態(tài)計(jì)算的

git對(duì)象 blob tree commit
git引用 分支引用 HEAD引用 標(biāo)簽引用 遠(yuǎn)程引用
git本地的遠(yuǎn)程分支也僅保存指針,不保存數(shù)據(jù)。數(shù)據(jù)保存在object中。遠(yuǎn)程分支標(biāo)記了commit object。(由于sha1的特點(diǎn),一般地,不同的文件不會(huì)具有相同的sha1)


Git分支與數(shù)據(jù)不直接關(guān)聯(lián)。
數(shù)據(jù)中文件內(nèi)容和文件元信息不直接關(guān)聯(lián)。
commit不和文件直接關(guān)聯(lián)。
遠(yuǎn)程分支建立在本地objects上,而不是簡(jiǎn)單粗暴地下載遠(yuǎn)程文件與本地文件比對(duì)。
git fetch操作是下載遠(yuǎn)程分支所關(guān)聯(lián)地object(如果有某個(gè)結(jié)點(diǎn)有兩個(gè)父節(jié)點(diǎn),那么這兩個(gè)方向的結(jié)點(diǎn)都會(huì)被下載),然后下載遠(yuǎn)程分支指針。
git是以節(jié)點(diǎn)鏈表為核心,不是以孤立的分支為核心。
git保證了與分支所關(guān)聯(lián)的commit可以被安全保存。
patch分支修改了某項(xiàng)功能,隨后在master分支上merge patch分支,刪除patch分支。這三個(gè)節(jié)點(diǎn)都得到了保留。

附加:
TortiseGit


文件修改 文件增加 文件刪除 文件重命名

git演示1

  • 新建倉(cāng)庫(kù)
    • 命令行中g(shù)it init
    • TortiseGit ,右鍵菜單Create repo
    • vs中 (待補(bǔ)充)
  • 創(chuàng)建文件
    • 手動(dòng)新建文件
    • 或者 echo “<字符>” >> new.txt
    • 或從 touch new.txt (windows下可能沒(méi)有此命令)
      打開(kāi)文件,寫(xiě)入new conent并保存
      注意:此時(shí) ./.git/objects文件夾內(nèi)并沒(méi)有生成對(duì)應(yīng)的文件

  • 將文件添加到index git add new.txt
    注意./git/objects/文件夾內(nèi)變化,增加了名為47的文件夾

  • 查看該文件夾的內(nèi)容


    使用git底層命令查看該文件的內(nèi)容git cat-file -p 47d2739ba2c34690248c8f91b84bb54e8936899a


    使用同樣的方法創(chuàng)建new.txt文件,并將其添加到index。在objects內(nèi)生成了23/b6fc220420f74c5af7f34c106ef931a1fa15ea文件

    注:47d2739ba2c34690248c8f91b84bb54e8936899a為內(nèi)容的sha1,實(shí)際上objects文件夾為數(shù)據(jù)庫(kù),sha1與內(nèi)容構(gòu)成了鍵值對(duì),按照<前2位sha1>/<后38位sha1>的方式存儲(chǔ)。

    注:將文件提交到index后,new.txt文件的內(nèi)容已經(jīng)被保存到了數(shù)據(jù)庫(kù)中。即git add的作用并不是僅對(duì)文件做標(biāo)記,而是將其內(nèi)容保存到數(shù)據(jù)庫(kù)中。可以將其分解為底層命令git hash-object,并未保存樹(shù)對(duì)象
    4.提交index到Local Repo

    git commit -m "First Commit"


    此時(shí),查看objects文件夾的內(nèi)容


    新增了5d/ d4/文件夾
    查看5d文件夾下新增文件的內(nèi)容
    使用git cat-file -p <sha1>指令查看新增objects的內(nèi)容
    使用git cat-file -t 指令查看新增objects的類(lèi)型


    查看d4文件夾下新增文件的內(nèi)容


    查看refs/heads文件夾


    查看master文件的內(nèi)容


    發(fā)現(xiàn)其內(nèi)容與新增的commit object的sha1一致。

    總結(jié):使用git commit指令后 objects內(nèi)新增兩個(gè)文件,分別為tree object,commit object。refs/heads文件夾內(nèi)分支指針內(nèi)容被改寫(xiě)。

  • 查看當(dāng)前HEAD指針的內(nèi)容,HEAD指針指向了master分支
    注:HEAD 與heads不同

  • 6.繼續(xù)測(cè)試,使用git commit --allow-empty -m "empty commit"指令進(jìn)行一次空提交
    注:使用windows下軟件everything 可以查看新增加的文件
    以下文件的修改時(shí)間與剛才的操作時(shí)間匹配


    分別為:

    • ./refs/heads/master
    • /logs/refs/heads/master
    • /logs/HEAD
    • 新增的object
    • COMMIT_EDITMSG (猜測(cè),此文件可能供git comment --amend 選項(xiàng)使用)
      查看master文件內(nèi)容,發(fā)現(xiàn)其指向了新的commit object
      logs文件夾內(nèi),有兩個(gè)文件發(fā)生了變化
      查看HEAD文件內(nèi)容,記錄了HEAD指針的變化,新記錄增加到文件末尾。第一個(gè)sha1值表示父commit,第二個(gè)sha1表示當(dāng)前的commit。第一次提交沒(méi)有父commit,所以用全0的sha1值表示。


    查看master文件內(nèi)容,記錄了master指針的變化,新記錄增加到文件末尾


    使用git log命令


    其內(nèi)容與logs內(nèi)文件內(nèi)容相似,不過(guò)最新的提交在頂部,從新到舊。
    使用命令git reflog


    記錄了HEAD指針的變化。
    注:HEAD@{N}表示HEAD之前的值

    提問(wèn):logs記錄的日志是否供git使用
    驗(yàn)證:將logs文件夾移動(dòng)其他位置,運(yùn)行g(shù)it log指令和git reflog指令
    運(yùn)行g(shù)it log指令,變更內(nèi)容仍可輸出
    運(yùn)行g(shù)it reflog指令,無(wú)內(nèi)容輸出。
    將logs文件夾移回,git reflog命令可正常使用
    總結(jié):git log遍歷objects來(lái)建立日志,git reflog查詢.git/logs文件夾下內(nèi)容

    注:git中箭頭含義,箭頭表示指向該節(jié)點(diǎn),不能把箭頭當(dāng)作時(shí)間方向

    TortiseGit介紹

    學(xué)習(xí)指導(dǎo):要從底層理解Git工作原理,將高層指令細(xì)分了若干低層操作。Git指令過(guò)多,且指令效果復(fù)雜,如果把Git當(dāng)作黑箱,則有些功能難以理解。從Git的基本工作原理入手


    Git Commit


    這里ReCommit表示完成此次提交后不關(guān)閉當(dāng)前窗口,可進(jìn)行下一次提交。(與amend last commit不同)


    Set author
    Set author date 在Message中添加作者和日期。
    Amend Last Commit (git commit --amend 修改上次提交)


    Show Unversioned Files 是否顯示未受版本控制的文件
    Message only 只提交Message,不提交文件


    show log同git log
    show reflog 同git reflog
    Browser References:瀏覽引用,即瀏覽分支
    Revision graph,顯示修訂版本圖(從圖中也可以看出,分支只是指針,不是分支實(shí)體)


    Repo Browser 倉(cāng)庫(kù)瀏覽器,可快速查看不同修訂版本的內(nèi)容,不需要修改Working-Tree內(nèi)容。

    git底層命令

    git hash-object 寫(xiě)入object
    git write-tree 將index內(nèi)容寫(xiě)入一個(gè)樹(shù)對(duì)象
    git update-index 更新index
    git cat-file [-p] [-t] [-s](pretty-print type size 查看文件

    git 內(nèi)部原理分析(參考git-scm)

    https://git-scm.com/book/zh/v2/Git-內(nèi)部原理-底層命令與上層命令

    1. git命令

    分為底層命令(plumbing),上層命令(porcelain)

    2. git文件目錄

    (注意,info/ 表示文件夾 HEAD 表示文件。根據(jù)末尾的/來(lái)區(qū)分文件和文件夾)config(config 文件包含項(xiàng)目特有的配置選項(xiàng))description(僅供 GitWeb 程序使用)HEAD(HEAD指針,指向目前被檢出的分支hooks/(包含客戶端或服務(wù)端的鉤子腳本)info/(目錄包含一個(gè)全局性排除(global exclude)文件, 用以放置那些不希望被記錄在 .gitignore 文件中的忽略模式(ignored patterns)objects/(目錄存儲(chǔ)所有數(shù)據(jù)內(nèi)容)refs/(存儲(chǔ)指向數(shù)據(jù)(分支、遠(yuǎn)程倉(cāng)庫(kù)和標(biāo)簽等)的提交對(duì)象的指針)index(文件保存暫存區(qū)信息)

    3. git對(duì)象

    • git對(duì)象(object)存放在./git/object/ 文件夾。以<hash的前兩位>/<hash的后38位>的結(jié)構(gòu)存儲(chǔ)
    • 對(duì)象分為 數(shù)據(jù)對(duì)象(blob object),樹(shù)對(duì)象(tree object),提交對(duì)象(commit object)
    • 數(shù)據(jù)對(duì)象僅保存了文件的內(nèi)容,沒(méi)有保存文件名。
      • git cat-file -p <指定的sha1> 從Git中取回?cái)?shù)據(jù)(-p 表示pretty-print 自動(dòng)判斷類(lèi)型 -t表示查看object的類(lèi)型
      • git hash-object -w test.txt 將test.txt寫(xiě)入Git
    • 樹(shù)對(duì)象(tree object)
      • 樹(shù)對(duì)象將文件組織到一起,一個(gè)樹(shù)對(duì)象包含了一條或多條樹(shù)對(duì)象記錄。每條記錄含有一個(gè)指向數(shù)據(jù)對(duì)象或者子樹(shù)對(duì)象的 SHA-1 指針,以及相應(yīng)的模式、類(lèi)型、文件名信息 * Git 根據(jù)某一時(shí)刻暫存區(qū)( index 區(qū)域,也稱(chēng)為stage區(qū)域,使用git
        add命令后文件被添加到這里)所表示的狀態(tài)創(chuàng)建并記錄一個(gè)對(duì)應(yīng)的樹(shù)對(duì)象。 * 底層命令 git
        update-index,必須為上述命令指定 --add
      • 文件模式為 100644,表明這是一個(gè)普通文件。 其他選擇包括:100755,表示一個(gè)可執(zhí)行文件; 120000,表示一個(gè)符號(hào)鏈接
      • git write-tree 命令將暫存區(qū)內(nèi)容寫(xiě)入一個(gè)樹(shù)對(duì)象
    • 提交對(duì)象(commit object)
      • 調(diào)用 commit-tree 命令創(chuàng)建一個(gè)提交對(duì)象。為此需要指定一個(gè)樹(shù)對(duì)象的 SHA-1 值,以及該提交的父提交對(duì)象(如果有的話)。
      • 如果你做完了以上所有操作,那么現(xiàn)在就有了三個(gè)樹(shù)對(duì)象,分別代表我們想要跟蹤的不同項(xiàng)目快照。 然而問(wèn)題依舊:若想重用這些快照,你必須記住所有三個(gè) SHA-1 哈希值。
        并且,你也完全不知道是誰(shuí)保存了這些快照,在什么時(shí)刻保存的,以及為什么保存這些快照。 而以上這些,正是提交對(duì)象(commit
        object)能為你保存的基本信息。
      • 提交對(duì)象 保存tree的sha1值,作者,保存時(shí)間,提交備注
      • 提交對(duì)象類(lèi)似于數(shù)據(jù)結(jié)構(gòu)中鏈表的結(jié)點(diǎn),保存自身信息和父節(jié)點(diǎn)的位置

    總結(jié)

  • git blob object保存文件內(nèi)容,tree object保存文件元信息以及目錄信息,commit tree保存提交信息。
  • 此時(shí),通過(guò)object的sha1來(lái)查找object,未對(duì)object進(jìn)行標(biāo)注。
  • 4.git引用(references,簡(jiǎn)寫(xiě)為refs)

    筆者注:git引用可以理解為C語(yǔ)言的指針,指向某個(gè)地址。引用存放在.git/refs/heads/
    對(duì)分支進(jìn)行操作時(shí)就是在操作【references】
    如果想更新某個(gè)引用,Git 提供了一個(gè)更加安全的命令 update-ref 來(lái)完成此事:
    Git 分支的本質(zhì):一個(gè)指向某一系列提交之首的指針或引用。

    HEAD 引用

    HEAD 文件通常是一個(gè)符號(hào)引用(symbolic reference),指向目前所在的分支。 所謂符號(hào)引用,表示它是一個(gè)指向其他引用的指針。

    標(biāo)簽引用

    然而實(shí)際上還有第四種。 標(biāo)簽對(duì)象(tag object) 非常類(lèi)似于一個(gè)提交對(duì)象——它包含一個(gè)標(biāo)簽創(chuàng)建者信息、一個(gè)日期、一段注釋信息,以及一個(gè)指針。 主要的區(qū)別在于,標(biāo)簽對(duì)象通常指向一個(gè)提交對(duì)象,而不是一個(gè)樹(shù)對(duì)象。 它像是一個(gè)永不移動(dòng)的分支引用——永遠(yuǎn)指向同一個(gè)提交對(duì)象,只不過(guò)給這個(gè)提交對(duì)象加上一個(gè)更友好的名字罷了。

    遠(yuǎn)程引用

    遠(yuǎn)程引用是只讀的。 雖然可以 git checkout 到某個(gè)遠(yuǎn)程引用,但是 Git 并不會(huì)將 HEAD 引用指向該遠(yuǎn)程引用。因此,你永遠(yuǎn)不能通過(guò) commit 命令來(lái)更新遠(yuǎn)程引用。 Git 將這些遠(yuǎn)程引用作為記錄遠(yuǎn)程服務(wù)器上各分支最后已知位置狀態(tài)的書(shū)簽來(lái)管理。

    參考資料

  • https://git-scm.com
  • 總結(jié)

    以上是生活随笔為你收集整理的git查看分支记录_git原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。