主頁 >  其他 > 深入理解Git的實作原理

深入理解Git的實作原理

2020-11-17 16:44:06 其他

  0、導讀   本文適合對git有過接觸,但知其然不知其所以然的小伙伴,也適合想要學習git的初學者,通過這篇文章,能讓大家對git有豁然開朗的感覺,在寫作程序中,我力求通俗易懂,深入淺出,不堆砌概念,你能夠從本文中了解以下知識:
  • Git是什么
  • Git能夠解決哪些問題
  • Git的實作原理

請注意,本文的闡述邏輯是:Git是什么——>Git要解決的根本問題是什么——>git是如何解決這些問題的,

1、Git是什么?   Git是一種分布式版本控制系統,   有人要問了,什么是“版本控制”?Git又為什么被冠以“分布式”的名頭呢?這兩個問題我們一一解答,   版本控制這個說法多少有一點抽象,事實上,版本控制這件事兒我們一直在做,只是平時不這么稱呼,舉一個栗子,boss讓你寫一個策劃案,你先完成了一稿,之后又有了一些新的想法,但是并不確定新的想法是否能得到boss的認可,于是你保存了一個初稿,之后在初稿的基礎上另存了一個檔案,做了部分修改完成了一個修改稿,OK,這時你的策劃案就有了兩個版本——初稿和修改稿,如果boss對修改稿不滿意,你可以很輕易的把初稿拿出來交差,   在這個簡單的程序中,你已經執行了一個簡單的版本控制操作——把檔案保存為初稿和修改稿的程序就是版本控制,   學術點說,版本控制就是對檔案變更程序的管理,說白了,版本控制就是要把一個檔案或一些檔案的各個版本按一定的方式管理起來,目的是需要用到某個版本的時候可以隨時拿出來,  

另一個個問題,為什么說Git是“分布式”版本控制系統呢?

這里的“分布式”是相對于“集中式”來說的,把資料集中保存在服務器節點,所有的客戶節點都從服務節點獲取資料的版本控制系統叫做集中式版本控制系統,比如svn就是典型的集中式版本控制系統,

與之相對,Git的資料不止保存在服務器上,同時也完整的保存在本地計算機上,所以我們稱Git為分布式版本控制系統,

Git的這種特性帶來許多便利,比如你可以在完全離線的情況下使用Git,隨時隨地提交專案更新,而且你不必為單點故障過分擔心,即使服務器宕機或資料損毀,也可以用任何一個節點上的資料恢復專案,因為每一個開發節點都保存著完整的專案檔案鏡像,

 

2、Git能夠解決哪些問題?   就像上文舉的例子一樣,在未接觸版本控制系統之前,大多人會通過保存專案或檔案的備份來達到版本控制的目的,通常你的檔案或檔案夾名會設定成“XXX-v1.0”、“XXX-v2.0”等,   這是一種簡單的辦法,但過于簡單,這種方式無法詳細記錄版本附加資訊,難以應付復雜專案或長期更新的專案,缺乏版本控制約定,對協作開發無能為力,如果你不慎使用了這種方式,那么稍稍過一段時間你就會發現連自己都不知道每個版本間的區別,版本控制形同虛設,   Git能夠為我們解決版本控制方面的大多數問題,利用Git  
  • 我們可以為每一次變更提交版本更新并且備注更新的內容;
  • 我們可以在專案的各個歷史版本之間自如切換;
  • 我們可以一目了然的比較出兩個版本之間的差異;
  • 我們可以從當前的修改中撤銷一些操作;
  • 我們可以自如的創建分支、合并分支;
  • 我們可以和多人協作開發;
  • 我們可以采取自由多樣的開發模式,
  諸如此類,數不勝數,然而實作這些功能的基礎是對檔案變更程序的存盤,如果我們能抓住這個根本,提綱挈領的學習git,會事半功倍,   隨著對Git更深入的學習,你會發現它會變得越來越簡單,越來越純粹,道家有萬法歸宗的說法,用在這里再合適不過,因為Git之所以有如此多炫酷的功能,根源只有一個:它很好的解決了檔案變更程序存盤這一個問題,

所以,如果問“Git能夠解決哪些問題?”我們可以簡單的回答:Git解決了版本控制方面的很多問題,但最核心的是它很好的解決了版本狀態存盤(即檔案變更程序存盤)的問題,

3、Git的實作原理   我們說到,Git很好的解決了版本狀態記錄的問題,在此基礎上實作了版本切換、差異比較、分支管理、分布式協作等等炫酷功能,那么,這一節我們就先從最根本的講起,看看Git是如何解決版本狀態記錄(即檔案變更程序記錄)問題的,   我們都有版本記錄的經驗,比如在檔案撰寫的關鍵點上保留一個備份,或在需要對檔案進行修改的時候“另存”一次,這都是很好的習慣,也是版本狀態記錄的一種常用方式,事實上,Git采取了差不多的方式,   在我們向Git系統提交一個版本的時候,Git會把這個版本完整保存下來,這是不是和“另存”有異曲同工之妙呢?不同之處在于存盤方式,在Git系統中一旦一個版本被提交,那么它就會被保存在“Git資料庫”中,   3.1 Git資料庫   我們提到了“Git資料庫”,這是什么玩意兒呢?為了能夠說清楚Git資料庫的概念,我們暫且引入三個Git指令,通過這三個命令,我們就能一探git資料庫的究竟,
  • git init  用于創建一個空的git倉庫,或重置一個已存在的git倉庫
  • git hash-object  git底層命令,用于向Git資料庫中寫入資料
  • git cat-file  git底層命令,用于查看Git資料庫中資料
  首先,我們用git init新建一個空的git倉庫,(希望小伙伴們可以跟著我的節奏一起來實際操作一下,會加深理解,如果有還沒有安裝好git工具的同學,請自行百度安裝,我不會講安裝的程序,)   我用的是ubuntu系統,在terminal下執行  

$ git init GitTest

Initialized empty Git repository in /home/mp/Workspace/GitTest/.git/

  這一命令在當前目錄下生成了一個新的檔案夾-GitTest,在GitTest中,包含了一個新建的空git倉庫,如果你不明白git倉庫是什么,那么可以簡單的理解為存放git資料的一個空間,這這個例子中,是“/home/mp/Workspace/GitTest/.git”目錄,   接下來,我們看看git倉庫的結構是什么樣的,執行  
$ cd GitTest $ ls $ find .git .git
.git/HEAD
.git/config
.git/objects
.git/objects/info
.git/objects/pack
.git/refs
.git/refs/heads
.git/refs/tags
.git/hooks
.git/hooks/commit-msg.sample
.git/hooks/post-update.sample
.git/hooks/update.sample
.git/hooks/pre-rebase.sample
.git/hooks/pre-applypatch.sample
.git/hooks/fsmonitor-watchman.sample
.git/hooks/applypatch-msg.sample
.git/hooks/pre-receive.sample
.git/hooks/pre-push.sample
.git/hooks/prepare-commit-msg.sample
.git/hooks/pre-commit.sample
.git/info
.git/info/exclude
.git/branches
.git/description

  我們發現,GitTest目錄下,除隱藏目錄.git之外,并沒有其他檔案或檔案夾,   我們通過find .git命令查看新生成的空git倉庫的結構,會發現其中有一個objects檔案夾,這就是git資料庫的存盤位置,   3.1 Git資料庫的寫入操作   緊接著,我們利用git底層命令git hash-object向git資料庫中寫入一些內容,執行命令:  

$ echo "version 1" | git hash-object -w --stdin

83baae61804e65cc73a7201a7252750c76066a30

$ find .git/objects/ -type f
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30

  "|"表示這是一條通道命令,意思是把“|”前邊的命令的輸出作為“|”后邊命令的輸入,git hash-object -w --stdin 的意思是向git資料庫中寫入一條資料(-w),這條資料的內容從標準輸入中讀取(--stdin),   命令執行后,會回傳個長度為40位的hash值,這個hash值是將待存盤的資料外加一個頭部資訊一起做SHA-1校驗運算而得的校驗和,在git資料庫中,它有一個名字,叫做“鍵值(key)”,相應的,git資料庫其實是一個簡單的“鍵值對(key-value)”資料庫,事實上,你向該資料庫中插入任意型別的內容,它都會回傳一個鍵值,通過回傳的鍵值可以在任意時刻再次檢索該內容,   此時,我們再次執行find .git/objects/ -type f命令查看objects目錄,會發現目錄中多出了一個檔案,這個檔案存盤在以新存入資料對應hash值的前2位命名的檔案夾內,檔案名為hash值的后38位,這就是git資料庫的存盤方式,一個檔案對應一條內容,就是這么簡單直接,   3.2 Git資料庫的查詢操作   我們可以通過git cat-file這個git底層命令查看資料庫中某一鍵值對應的資料,執行  
$ git cat-file -t  83baa blob

$ git cat-file -p 83baa version 1
  其中,-t選項用于查看鍵值對應資料的型別,-p選項用于查看鍵值對應的資料內容,83bba為資料鍵值的簡寫,   由執行結果可見,所查詢的鍵值對應的資料型別為blob,資料內容為“version 1”,blob物件我們稱之為資料物件,這是git資料庫能夠存盤的物件型別之一,后面我們還會講到另外兩種物件分別是樹(tree)物件和提交(commit)物件,   截止到這里,你已經掌握了如何向git資料庫里存入內容和取出內容,這很簡單但是卻意義非凡,因為對git資料庫的操作正是git系統的核心——git的版本控制功能就是基于它的物件資料庫實作的,在git資料庫里,存盤著納入git版本管理的所有檔案的所有版本的完整鏡像,   git這么簡單嗎?不用懷疑,git就是這么簡單,我們已經準確的抓住了它的根本要義——物件資料庫,接下來我們會利用git資料庫搭建起git的高樓大廈,   3.3 使用Git跟蹤檔案變更   我們明白,所謂跟蹤檔案變更,只不過是把檔案變更程序中的各個狀態完整記錄下來,   我們模擬一次檔案變更的程序,看看僅僅利用git的物件資料庫能不能實作“跟蹤檔案變更”的功能,   首先,我們執行  
$ echo "version 1" > file.txt   $ git hash-object -w file.txt 83baae61804e65cc73a7201a7252750c76066a30
  我們把文本“version 1”寫入file.txt中,并利用git hash-object -w file.txt命令將其保存入資料庫中,如果你足夠細心,會發現回傳的hash鍵值和利用echo "version 1" | git hash-object -w --stdin寫入資料庫時是一致的,這很正常,因為我們寫入的內容相同,git hash-object命令在只指定-w選項的時候,會把file.txt檔案內容寫入資料庫,

此時,執行  

$ find .git/objects -type f

.git/objects/83/baae61804e65cc73a7201a7252750c76066a30

  會發現.git/objects目錄中,依然只有一個檔案,可見,git資料庫存盤檔案時,只關心檔案內容,與檔案的名字無關,

接下來,我們修改file.txt的內容,執行  
$ echo "version 2" > file.txt $ git hash-object -w file.txt 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a $ find .git/objects -type f .git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30

 
我們發現,.git/objects下多出了一個檔案,這是我們新保存進資料庫的file.txt,接下來,我們執行git cat-file搞清楚這兩條資料的內容分別是什么,執行  
$git cat-file -p 83baa version 1 $git cat-file -p 1f7a7a version 2
 
我們發現,file.txt的變更程序被完整的記錄下來了,   當前的file.txt中保存的內容是“version 2”,如果我們想把檔案恢復到修改為“version 2”之前的狀態,只需執行  
$ cat file.txt
version 2 $ git cat-file -p 83baa > file.txt $ cat file.txt
version 1

file.txt的內容成功恢復到了修改前的狀態,變成了“version 1”,這其實就是版本回滾的實質,

OK,檔案變更狀態跟蹤的道理就是這么簡單,   但做到這一步還遠遠不算完美,至少有以下幾方面的問題:

  • 第一,無法記錄檔案名的變化;
  • 第二,無法記錄檔案夾的變化;
  • 第三,記憶每一個版本對應的hash值無聊且乏味且不可能;
  • 第四,無法得知檔案的變更時序;
  • 第五,缺少對每一次版本變化的說明,
問題不少,但都是簡單的小問題,我們一一解決,   3.4 利用樹物件(tree object)解決檔案名保存和檔案組織問題   Git利用樹物件(tree object)解決檔案名保存的問題,樹物件也能夠將多個檔案組織在一起,

Git通過樹(tree)物件將資料(blob)物件組織起來,這很類似于一種檔案系統——blob物件對應檔案內容,tree物件對應檔案的目錄和節點,一個樹(tree)物件包含一潭訓多條記錄,每條記錄含有一個指向blob物件或tree物件的SHA-1指標,以及相應的模式、型別、檔案名,   有了樹物件,我們就可以將檔案系統任何時間點的狀態保存在git資料庫中,這是不是很激動人心呢?你的一個復雜的專案可能包含成百上千個檔案和檔案目錄,有了樹物件,這一切都不是問題,   創建樹物件   通常,Git根據某一時刻暫存區所表示的狀態創建并記錄一個對應的樹物件,如此重復便可以依次記錄一系列的樹物件,Git的暫存區是一個檔案——.git/index,下面,我們通過創建樹物件的程序來認識暫存區和樹物件,   為了創建一個樹物件,我們需要通過暫存一些檔案來創建一個暫存區,為此我們引入兩個命令:  
  • git update-index     git底層命令,用于創建暫存區
  • git ls-files --stage    git底層命令,用于查看暫存區內容
  • git write-tree            git底層命令,用于將暫存區內容寫入一個樹物件

OK,萬事俱備,我們將file.txt的第一個版本放入暫存區,執行  
$ find .git/index
find: ‘.git/index’: No such file or directory
$ git update-index --add file.txt
$ find .git/index
.git/index
$ cat .git/index
DIRC[???$?;?[???$?;?A????
???a?Ne?s? rRu
               vjfile.txt??3%A??,I? ?`
$ find .git/objects/ -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
$ git ls-files --stage
100644 83baae61804e65cc73a7201a7252750c76066a30 0    file.txt
$ git write-tree
391a4e90ba882dbc9ea93855103f6b1fa6791cf6
$ find .git/objects/ -type f
.git/objects/39/1a4e90ba882dbc9ea93855103f6b1fa6791cf6
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30


 分析執行結果:   首先,我們注意.git/index檔案的變化,在添加file.txt到暫存區前,index檔案并不存在,這說明暫存區還沒有創建,添加file.txt到暫存區的同時,index檔案被創建,   其次,我們看git資料庫的變化,我們發現在執行git update-index 之后,git資料庫并沒有改變,依然是只有兩條資料,在執行git write-tree之后,git資料庫中多出了一條新的記錄,鍵值為391a4e90ba882dbc9ea93855103f6b1fa6791cf6,   我們執行git cat-file來查看一下多出來的這條記錄是什么內容,執行  
$ git cat-file -t 391a4e
tree
$ git cat-file -p 391a4e
100644 blob 83baae61804e65cc73a7201a7252750c76066a30    file.txt
  由執行結果可見,git資料庫中新增加的記錄是一個tree物件,該tree物件指向一個blob物件,hash鍵值為  
83baae61804e65cc73a7201a7252750c76066a30
  這一個blob物件是之前我們添加進資料庫的,

以上我們添加了一個已經存在在git資料庫中的檔案到暫存區,如果我們新建一個未曾保存到git資料庫的檔案存入暫存區,進而保存為tree物件,會有什么不同嗎?我們試試看,執行  

$ echo "new file" > new
$ git update-index --add new
$ find .git/objects/ -type f
.git/objects/39/1a4e90ba882dbc9ea93855103f6b1fa6791cf6 #tree物件
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a #blob物件
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30 #blob物件
.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 #新增的blob物件
$ git write-tree
228e49bb0bf19df94b49c3474f5d4ee55a371fbe #新生成的tree物件鍵值
$ find .git/objects/ -type f
.git/objects/39/1a4e90ba882dbc9ea93855103f6b1fa6791cf6
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92
.git/objects/22/8e49bb0bf19df94b49c3474f5d4ee55a371fbe #新增的tree物件

$ git ls-files --stage
100644 83baae61804e65cc73a7201a7252750c76066a30 0    file.txt
100644 fa49b077972391ad58037050f2a75f74e3671e92 0    new

  由執行結果我們可以看到,這一次執行update-index之后,和上次不同,git資料庫發生了變化,新增加了一條hash鍵值為“fa49b0”的資料;暫存區中也多出了檔案new的資訊,

這說明兩個問題:
  • 如果添加git資料庫中尚未存盤的資料到暫存區,則在執行update-index的時候,會同時把該資料保存到git資料庫,
  • 添加檔案進入暫存區的操作是追加操作,之前已經加入暫存區的檔案依然存在——很多人會有誤區,認為變更提交之后,暫存區就清空了,
此時,我們查看新添加的樹物件,執行

$ git cat-file -p 228e49
100644 blob 83baae61804e65cc73a7201a7252750c76066a30    file.txt
100644 blob fa49b077972391ad58037050f2a75f74e3671e92    new
  此次write-tree寫入資料庫的是tree物件包含了兩個檔案,   更進一步,我們是否能將一個子檔案夾保存到樹物件呢?嘗試一下,執行  
$ mkdir new_dir
$ git update-index --add new_dir
error: new_dir: is a directory - add files inside instead
fatal: Unable to process path new_dir
  我們發現,無法將一個新建的空檔案夾添加到暫存區,錯誤提示告訴我們,應該將檔案將檔案夾中的檔案加入到暫存區(add files inside instead),

OK,接下來,我們在新建的檔案夾下寫入一個檔案,再嘗試將這一檔案加入暫存區,執行  

$ echo "file in new dir" > new_dir/new
$ git update-index --add new_dir/new
$ git ls-files --stage
100644 83baae61804e65cc73a7201a7252750c76066a30 0    file.txt
100644 fa49b077972391ad58037050f2a75f74e3671e92 0    new
100644 138c554a661371c9c40ae62dfb5d51b48b9b3f6b 0    new_dir/new

$ git write-tree
06564b76e0fcf9f3600fd055265cf2d4c45847a8

$ git cat-file -p 06564b
100644 blob 83baae61804e65cc73a7201a7252750c76066a30    file.txt
100644 blob fa49b077972391ad58037050f2a75f74e3671e92    new
040000 tree 8d6bc0bdbba1d28caf4ee66a125169500080e206    new_dir


從執行結果可見,檔案夾new_dir對應一個tree物件,
至此,在git資料庫中,我們可以完整的記錄檔案的狀態、檔案夾的狀態;并且可以把多個檔案或檔案夾組織在一起,記錄他們的變更程序,我們離一個完善的版本控制系統似乎已經不遠了,而這一切實作起來又是如此簡單——我們只是通過幾個命令操作git資料庫就完成了這些功能,   接下來,我們只要把資料庫中各個版本的時序關系記錄下來,再把對每一個版本更新的注釋記錄下來,不就完成了一個邏輯簡單、功能強大、操作靈活的版本控制系統嗎?   那么,如何記錄版本的時序關系,如何記錄版本的更新注釋呢?這就要引入另一個git資料物件——提交物件(commit object),   3.5 利用提交物件(commit object)記錄版本間的時序關系和版本注釋   commit物件能夠幫你記錄什么時間,由什么人,因為什么原因提交了一個新的版本,這個新的版本的父版本又是誰,   git提供了底層命令commit-tree來創建提交物件(commit object),我們需要為這個命令指定一個被提交的樹物件的hash鍵值,以及該提交物件的父提交物件(如果是第一次提交,不需要指定父物件),   我們嘗試將之前創建的樹物件提交為commit 物件,執行
$ git write-tree cb0fbcc484a3376b3e70958a05be0299e57ab495
$ git commit-tree cb0fbcc -m "first commit" 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f
$ git cat-file 7020a97 tree cb0fbcc484a3376b3e70958a05be0299e57ab495
author john <[email protected]> 1537961478 +0800
committer john <[email protected]> 1537961478 +0800

first commit
  在git commit-tree命令中,-m選項用于指定本次提交的注釋,   我們可以很清楚的看到,一個提交物件包含著所提交版本的樹物件hash鍵值,author和commiter,以及修改和提交的時間,最后是本次提交的注釋,   其中committer和author是通過git config命令設定的,   接下來,修改某個檔案,重新創建一個樹物件,并將這一樹物件提交,作為專案的第二個提交版本,執行
$ echo "new version" > file.txt $ git update-index file.txt $ git write-tree
848e967643b947124acacc3a2d6c5a13c549231c
$ git commit-tree 848e96 -p 7020a97 -m "second commit"
e838c8678ef789df84c2666495663060c90975d7
$ git cat-file -p e838c
tree 848e967643b947124acacc3a2d6c5a13c549231c
parent 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f
author john <[email protected]> 1537962442 +0800
committer john <[email protected]> 1537962442 +0800

second commit
  我們可以按照上述步驟,再提交第三個版本,  
$ echo "another version" > file.txt
$ git update-index file.txt
$ git write-tree
92867fcc5e0f78c195c43d1de25aa78974fa8103
$ git commit-tree 92867 -p e838c -m "third commit"
491404fa6e6f95eb14683c3c06d10ddc5f8e883f
$ git cat-file -p 49140
tree 92867fcc5e0f78c195c43d1de25aa78974fa8103
parent e838c8678ef789df84c2666495663060c90975d7
author john <[email protected]> 1537963274 +0800
committer john <[email protected]> 1537963274 +0800

 

third commit
  提交完三個版本,我們通過git log 查看最近一個提交物件的提交記錄  
$ git log 49140
commit 491404fa6e6f95eb14683c3c06d10ddc5f8e883f
Author: john <[email protected]>
Date:   Wed Sep 26 20:01:14 2018 +0800

    third commit

commit e838c8678ef789df84c2666495663060c90975d7
Author: john <[email protected]>
Date:   Wed Sep 26 19:47:22 2018 +0800

    second commit

commit 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f
Author: john <[email protected]>
Date:   Wed Sep 26 19:31:18 2018 +0800

    first commit

  太神奇了: 就在剛才,我們圍繞git資料庫,僅憑幾個底層資料庫操作便完成了一個 Git 提交歷史的創建,到此為止,我們已經完全掌握了git的內在邏輯,   接觸過git的小伙伴會發現,以上我們用到的這些指令在使用git程序中是用不到的,這是為什么呢?因為git對以上這些指令進行了封裝,給用戶提供了更便捷的操作命令,如add,commit等,   每次我們運行 git addgit commit 命令時, Git 所做的實質作業是將被改寫的檔案保存為資料物件,更新暫存區,記錄樹物件,最后創建一個指明了頂層樹物件和父提交的提交物件, 這三種主要的 Git 物件——資料物件、樹物件、提交物件——最初均以單獨檔案的形式保存在 .git/objects 目錄下,   然而,小問題依然存在,截止目前為止,我們對版本和資料物件的操作都是基于hash鍵值的,這些毫無直觀含義的字串讓人很頭疼,不會有人愿意一直急著最新提交對應的hash鍵值的,git不會允許這樣的問題存在的,它通過引入“參考(references)”來解決這一問題,   3.6 Git的參考
  Git的參考(references)保存在.git/refs目錄下,git的參考類似于一個指標,它指向的是某一個hash鍵值,   創建一個參考實在再簡單不過,我們只需把一個git物件的hash鍵值保存在以參考的名字命名的檔案中即可,   執行
$ echo "491404fa6e6f95eb14683c3c06d10ddc5f8e883f" > .git/refs/heads/master
$ cat .git/refs/heads/master
491404fa6e6f95eb14683c3c06d10ddc5f8e883f
  就這樣,我們便成功的建立了一個指向最新一個提交的參考,參考名為master   在此之前我們查看提交記錄需要執行 git log 491404,現在只需執行git log master,  
$ git log 491404
commit 491404fa6e6f95eb14683c3c06d10ddc5f8e883f (HEAD -> master)
Author: john <[email protected]>
Date: Wed Sep 26 20:01:14 2018 +0800

 

third commit

 

commit e838c8678ef789df84c2666495663060c90975d7
Author: john <[email protected]>
Date: Wed Sep 26 19:47:22 2018 +0800

 

second commit

 

commit 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f
Author: john <[email protected]>
Date: Wed Sep 26 19:31:18 2018 +0800

 

first commit
$ git log master
commit 491404fa6e6f95eb14683c3c06d10ddc5f8e883f (HEAD -> master)
Author: john <[email protected]>
Date: Wed Sep 26 20:01:14 2018 +0800

 

third commit

 

commit e838c8678ef789df84c2666495663060c90975d7
Author: john <[email protected]>
Date: Wed Sep 26 19:47:22 2018 +0800

 

second commit

 

commit 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f
Author: john <[email protected]>
Date: Wed Sep 26 19:31:18 2018 +0800

 

first commit

  結果完全相同,   Git并不提倡直接編輯參考檔案,它提供了一個底層命令update-ref來創建或修改參考檔案,   echo "491404fa6e6f95eb14683c3c06d10ddc5f8e883f" > .git/refs/heads/master 命令可以簡單的寫作:  
$ git update-ref refs/heads/master 49140
  這基本就是 Git 分支的本質:一個指向某一系列提交之首的指標或參考,   4. Git基本原理總結     Git的核心是它的物件資料庫,其中保存著git的物件,其中最重要的是blob、tree和commit物件,blob物件實作了對檔案內容的記錄,tree物件實作了對檔案名、檔案目錄結構的記錄,commit物件實作了對版本提交時間、版本作者、版本序列、版本說明等附加資訊的記錄,這三類物件,完美實作了git的基礎功能:對版本狀態的記錄,   Git參考是指向git物件hash鍵值的類似指標的檔案,通過Git參考,我們可以更加方便的定位到某一版本的提交,Git分支、tags等功能都是基于Git參考實作的,  

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/222250.html

標籤:其他

上一篇:關于時間的那些事--PHP、JavaScript、MySQL操作時間

下一篇:【IT技術】常見的互聯網推薦演算法集,看完我跪了!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more