git查看分支记录_git原理
標準用法請參考git-scm。本文記錄筆者對git的一些理解,如有錯誤,歡迎指正。
引用內(nèi)容已用markdown記號標出。版權所有,轉(zhuǎn)載請注明出處。
文章完成中
First Edition:2021-01-27
文中的記號約定
<當前分支>:用尖括號包裹,需要被替換
軟件環(huán)境
筆者將介紹 命令行,TortiseGit,VS中git的使用
git學習指引
更適合把git當作某種數(shù)據(jù)結構來理解,從底層理解git
git中的一些概念
git分支并不是一個實體,而是一個指針,分支只存放了指向某個commit的指針,不保存其他信息。在master分支創(chuàng)建新提交后,分支指針指向為新的commit。
HEAD表示當前指向的位置,master/main一般用于主分支。不要混淆兩者概念
working-tree index lib
working-tree為工作目錄,即可以直接操作
index,也稱stage,git commit將當前index狀態(tài)保存,即git commit不處理工作目錄
git基本命令
- add 添加文件到index
- commit 將當前index提交到Local Repository
- checkout 修改HEAD指針 底層修改 ./git/HEAD
- switch 修改HEAD指針,使其指向某個分支而不是某個結點
- branch 創(chuàng)建分支
- reset 修改當前分支的指針 底層修改文件 ./git/refs/head/<分支名>
git指令
git rebase
git revert
git reset
git checkout
git merge
git cherry-pick
git merge命令
當前工作再branch_master分支,此分支指向commitA,develop分支指向commitB,(AB字母僅供標識,沒有其他含義)。使用指令git merge develop,創(chuàng)建一個新的commitC,commitC以commitA和commitB為父結點。再次強調(diào),git的分支是一個指針,存放在./git/refs文件夾下。分支所包含的結點是以類似鏈表的方式的進行查找的,并不是線性記錄在某個文件中。
git中刪除分支并不會直接刪除commit object,不過分支指針丟失了,難以進行查找,并且git有gc垃圾回收機制,會清理懸掛對象。(git誤操作后恢復數(shù)據(jù)原理,分支指針被清除,對象并未清除,而且在./git/logs文件夾內(nèi)有日志。) git fsck 命令驗證數(shù)據(jù)庫中對象的連通性和有效性。
git revert命令
當前master分支有commitA commitB commitC
使用git revert commitA命令生成commitD,commitD的父節(jié)點為commitC,commitD的內(nèi)容與A一致,但并不破壞歷史記錄.
注:git對象是以鏈表的形式組織。鏈表上的結點不能自由移動,但可以對讀取結點上的內(nèi)容,創(chuàng)建新結點,這看起來像是回到了某次提交。
git reset命令
修改當前分支指向的結點(分支指針總是指向該分支的最后一個結點,或者說分支指針記錄了該分支最后一個結點,checkout命令是移動HEAD指針)
當前master分支有commitA commitB commitC
git reset commitA后,如果沒有分支線包含commitB,commitC,那么B、C不會顯示在git log中(因為git log是動態(tài)搜索),B、C可能會被清除。
注:git使用鏈接式的數(shù)據(jù)結構。
git cherry-pick命令
git區(qū)域
這幾個區(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,修改當前分支的指針,在logs文件夾內(nèi)寫入HEAD和當前分支的變更日志。
在git中,數(shù)據(jù)存放在以sha1為鍵名的數(shù)據(jù)庫中,以鏈表方式組織數(shù)據(jù)。這樣數(shù)據(jù)更加靈活。
git reflog是保存到本地的,不保存到遠程。git log是動態(tài)計算的
git對象 blob tree commit
git引用 分支引用 HEAD引用 標簽引用 遠程引用
git本地的遠程分支也僅保存指針,不保存數(shù)據(jù)。數(shù)據(jù)保存在object中。遠程分支標記了commit object。(由于sha1的特點,一般地,不同的文件不會具有相同的sha1)
Git分支與數(shù)據(jù)不直接關聯(lián)。
數(shù)據(jù)中文件內(nèi)容和文件元信息不直接關聯(lián)。
commit不和文件直接關聯(lián)。
遠程分支建立在本地objects上,而不是簡單粗暴地下載遠程文件與本地文件比對。
git fetch操作是下載遠程分支所關聯(lián)地object(如果有某個結點有兩個父節(jié)點,那么這兩個方向的結點都會被下載),然后下載遠程分支指針。
git是以節(jié)點鏈表為核心,不是以孤立的分支為核心。
git保證了與分支所關聯(lián)的commit可以被安全保存。
patch分支修改了某項功能,隨后在master分支上merge patch分支,刪除patch分支。這三個節(jié)點都得到了保留。
附加:
TortiseGit
文件修改 文件增加 文件刪除 文件重命名
git演示1
- 命令行中git init
- TortiseGit ,右鍵菜單Create repo
- vs中 (待補充)
- 手動新建文件
- 或者 echo “<字符>” >> new.txt
- 或從 touch new.txt (windows下可能沒有此命令)
打開文件,寫入new conent并保存
注意:此時 ./.git/objects文件夾內(nèi)并沒有生成對應的文件
注意./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,實際上objects文件夾為數(shù)據(jù)庫,sha1與內(nèi)容構成了鍵值對,按照<前2位sha1>/<后38位sha1>的方式存儲。
注:將文件提交到index后,new.txt文件的內(nèi)容已經(jīng)被保存到了數(shù)據(jù)庫中。即git add的作用并不是僅對文件做標記,而是將其內(nèi)容保存到數(shù)據(jù)庫中。可以將其分解為底層命令git hash-object,并未保存樹對象
4.提交index到Local Repo
此時,查看objects文件夾的內(nèi)容
新增了5d/ d4/文件夾
查看5d文件夾下新增文件的內(nèi)容
使用git cat-file -p <sha1>指令查看新增objects的內(nèi)容
使用git cat-file -t 指令查看新增objects的類型
查看d4文件夾下新增文件的內(nèi)容
查看refs/heads文件夾
查看master文件的內(nèi)容
發(fā)現(xiàn)其內(nèi)容與新增的commit object的sha1一致。
總結:使用git commit指令后 objects內(nèi)新增兩個文件,分別為tree object,commit object。refs/heads文件夾內(nèi)分支指針內(nèi)容被改寫。
注:HEAD 與heads不同
6.繼續(xù)測試,使用git commit --allow-empty -m "empty commit"指令進行一次空提交
注:使用windows下軟件everything 可以查看新增加的文件
以下文件的修改時間與剛才的操作時間匹配
分別為:
- ./refs/heads/master
- /logs/refs/heads/master
- /logs/HEAD
- 新增的object
- COMMIT_EDITMSG (猜測,此文件可能供git comment --amend 選項使用)
查看master文件內(nèi)容,發(fā)現(xiàn)其指向了新的commit object
logs文件夾內(nèi),有兩個文件發(fā)生了變化
查看HEAD文件內(nèi)容,記錄了HEAD指針的變化,新記錄增加到文件末尾。第一個sha1值表示父commit,第二個sha1表示當前的commit。第一次提交沒有父commit,所以用全0的sha1值表示。
查看master文件內(nèi)容,記錄了master指針的變化,新記錄增加到文件末尾
使用git log命令
其內(nèi)容與logs內(nèi)文件內(nèi)容相似,不過最新的提交在頂部,從新到舊。
使用命令git reflog
記錄了HEAD指針的變化。
注:HEAD@{N}表示HEAD之前的值
提問:logs記錄的日志是否供git使用
驗證:將logs文件夾移動其他位置,運行git log指令和git reflog指令
運行git log指令,變更內(nèi)容仍可輸出
運行git reflog指令,無內(nèi)容輸出。
將logs文件夾移回,git reflog命令可正常使用
總結:git log遍歷objects來建立日志,git reflog查詢.git/logs文件夾下內(nèi)容
注:git中箭頭含義,箭頭表示指向該節(jié)點,不能把箭頭當作時間方向
TortiseGit介紹
學習指導:要從底層理解Git工作原理,將高層指令細分了若干低層操作。Git指令過多,且指令效果復雜,如果把Git當作黑箱,則有些功能難以理解。從Git的基本工作原理入手
Git Commit
這里ReCommit表示完成此次提交后不關閉當前窗口,可進行下一次提交。(與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,顯示修訂版本圖(從圖中也可以看出,分支只是指針,不是分支實體)
Repo Browser 倉庫瀏覽器,可快速查看不同修訂版本的內(nèi)容,不需要修改Working-Tree內(nèi)容。
git底層命令
git hash-object 寫入object
git write-tree 將index內(nèi)容寫入一個樹對象
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ù)末尾的/來區(qū)分文件和文件夾)config(config 文件包含項目特有的配置選項)description(僅供 GitWeb 程序使用)HEAD(HEAD指針,指向目前被檢出的分支hooks/(包含客戶端或服務端的鉤子腳本)info/(目錄包含一個全局性排除(global exclude)文件, 用以放置那些不希望被記錄在 .gitignore 文件中的忽略模式(ignored patterns)objects/(目錄存儲所有數(shù)據(jù)內(nèi)容)refs/(存儲指向數(shù)據(jù)(分支、遠程倉庫和標簽等)的提交對象的指針)index(文件保存暫存區(qū)信息)3. git對象
- git對象(object)存放在./git/object/ 文件夾。以<hash的前兩位>/<hash的后38位>的結構存儲
- 對象分為 數(shù)據(jù)對象(blob object),樹對象(tree object),提交對象(commit object)
- 數(shù)據(jù)對象僅保存了文件的內(nèi)容,沒有保存文件名。
- git cat-file -p <指定的sha1> 從Git中取回數(shù)據(jù)(-p 表示pretty-print 自動判斷類型 -t表示查看object的類型
- git hash-object -w test.txt 將test.txt寫入Git
- 樹對象(tree object)
- 樹對象將文件組織到一起,一個樹對象包含了一條或多條樹對象記錄。每條記錄含有一個指向數(shù)據(jù)對象或者子樹對象的 SHA-1 指針,以及相應的模式、類型、文件名信息 * Git 根據(jù)某一時刻暫存區(qū)( index 區(qū)域,也稱為stage區(qū)域,使用git
add命令后文件被添加到這里)所表示的狀態(tài)創(chuàng)建并記錄一個對應的樹對象。 * 底層命令 git
update-index,必須為上述命令指定 --add - 文件模式為 100644,表明這是一個普通文件。 其他選擇包括:100755,表示一個可執(zhí)行文件; 120000,表示一個符號鏈接
- git write-tree 命令將暫存區(qū)內(nèi)容寫入一個樹對象
- 樹對象將文件組織到一起,一個樹對象包含了一條或多條樹對象記錄。每條記錄含有一個指向數(shù)據(jù)對象或者子樹對象的 SHA-1 指針,以及相應的模式、類型、文件名信息 * Git 根據(jù)某一時刻暫存區(qū)( index 區(qū)域,也稱為stage區(qū)域,使用git
- 提交對象(commit object)
- 調(diào)用 commit-tree 命令創(chuàng)建一個提交對象。為此需要指定一個樹對象的 SHA-1 值,以及該提交的父提交對象(如果有的話)。
- 如果你做完了以上所有操作,那么現(xiàn)在就有了三個樹對象,分別代表我們想要跟蹤的不同項目快照。 然而問題依舊:若想重用這些快照,你必須記住所有三個 SHA-1 哈希值。
并且,你也完全不知道是誰保存了這些快照,在什么時刻保存的,以及為什么保存這些快照。 而以上這些,正是提交對象(commit
object)能為你保存的基本信息。 - 提交對象 保存tree的sha1值,作者,保存時間,提交備注
- 提交對象類似于數(shù)據(jù)結構中鏈表的結點,保存自身信息和父節(jié)點的位置
總結
4.git引用(references,簡寫為refs)
筆者注:git引用可以理解為C語言的指針,指向某個地址。引用存放在.git/refs/heads/
對分支進行操作時就是在操作【references】
如果想更新某個引用,Git 提供了一個更加安全的命令 update-ref 來完成此事:
Git 分支的本質(zhì):一個指向某一系列提交之首的指針或引用。
HEAD 引用
HEAD 文件通常是一個符號引用(symbolic reference),指向目前所在的分支。 所謂符號引用,表示它是一個指向其他引用的指針。
標簽引用
然而實際上還有第四種。 標簽對象(tag object) 非常類似于一個提交對象——它包含一個標簽創(chuàng)建者信息、一個日期、一段注釋信息,以及一個指針。 主要的區(qū)別在于,標簽對象通常指向一個提交對象,而不是一個樹對象。 它像是一個永不移動的分支引用——永遠指向同一個提交對象,只不過給這個提交對象加上一個更友好的名字罷了。遠程引用
遠程引用是只讀的。 雖然可以 git checkout 到某個遠程引用,但是 Git 并不會將 HEAD 引用指向該遠程引用。因此,你永遠不能通過 commit 命令來更新遠程引用。 Git 將這些遠程引用作為記錄遠程服務器上各分支最后已知位置狀態(tài)的書簽來管理。參考資料
總結
以上是生活随笔為你收集整理的git查看分支记录_git原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么开不了4g网络_为什么4G网络越来
- 下一篇: kafka offset保存在哪里_《K