主頁 > 作業系統 > gitlog中的“替換”是什么意思?

gitlog中的“替換”是什么意思?

2021-11-29 11:16:32 作業系統

當我這樣做時git log --all,我在日志中發現了一個有趣的提交:

commit 3a1a6bfbd936ea441ecf1f071e82f89c7e8bbf6c (replaced, origin/main)

replaced括號中的關鍵字是什么意思?以及如何觸發?

uj5u.com熱心網友回復:

這意味著有人使用git replace.

什么git replace是允許你告訴未來的 Git 操作,而不是一些原始物件,他們應該查看一些替換物件。本段介紹了替換的作業原理,但沒有告訴您這一切意味著什么問題是,在這個層面上,意義還不存在。這就像說中子俘獲導致 U-235 原子核裂變成兩個重量更輕的原子核,發射出兩個中子沒錯,但那又怎樣?那么,核反應堆或原子彈。我們已經從干核物理走向了嚴重的后果。

幸運的是,Git 替換并不是那么引人注目。但是一個簡單的替換可能會產生巨大的后果。它的后果有,在你的資料庫,是不是我們可以提前確定。我們所能做的就是描述替換背后的想法。

替換背后的想法

任何Git 物件,一旦創建,都是只讀的,并且只要有人/某事正在使用它,就會繼續存在于存盤庫中。這種只讀質量的原因是每個物件都通過其哈希 ID 在鍵值資料庫中找到(或尋址,用一個奇特的術語),在一個鍵值資料庫中,其鍵是哈希 ID,其值是哈希物件。當 Git 從資料庫中提取物件時,Git 會重新計算散列,并驗證檢索到的物件的散列是否與用于檢索物件的鍵匹配。這保證了物件資料不會損壞。1

如果我們在進行新提交時犯了一個錯誤,而其他人現在沒有在使用,并且可以快速檢測到我們自己的錯誤,我們可以通過用新提交快速替換原始提交來糾正我們的錯誤。我們的原始提交只能通過存盤在某個分支名稱中的哈希 ID找到如果我們為它做一個新的替換提交,并糾正錯誤,新的提交將有一些其他不同的哈希 ID。我們存盤新的替代單位犯的哈希ID分行名稱(這可寫的),我們就大功告成了:“壞”的承諾仍然存在,但未被使用。在沒有人使用它的情況下,Git 最終會完全放棄它。2

這對于提交來說很好,其哈希 ID 僅存盤在單個分支名稱中。但是如果提交不是那么新呢?特別是,提交哈希 ID 存盤在以后的提交中如果這個“壞”提交是提交鏈的一部分,我們就有問題了。

請記住,提交形成后向鏈,通過分支名稱找到,該分支名稱指向 Git 所謂的提示提交:鏈中的最后一次提交。也就是說,給定一系列提交,每個提交都有自己的哈希 ID,我們可以使用單個大寫字母代表哈希 ID 來繪制它們:

... <-F <-G <-H   <--main

名稱 main指向提交,其哈希值H該提交向后指向較早的提交GCommitG向后指向更早的 commit F,依此類推。

如果 commit 有錯誤F,我們可以嘗試做git commit --amend它所做的:制作一個新的和改進的F'并推開F

     F ...
    /
... <-F'

但是當我們這樣做時,現有的提交G——字面上包含現有提交的哈希 IDF并且不能更改——仍然指向F

     F <-G <-H   <--main
    /
... <-F'

我們簡單的修改嘗試是F行不通的,因為main指向的不是F,而是HH指向G,并將永遠這樣做。 G指向F,并將永遠這樣做。我們可以復制GH到新的和改進的G'H'

     F <-G <-H   <--main
    /
... <-F' <-G' <-H'

并作出3份,我們現在可以重新點的分支名稱main

     F <-G <-H
    /
... <-F' <-G' <-H'   <--main

這就是git rebase它的作用。但它的缺點是之后的每次提交F必須被復制。如果有復雜的鏈:

             I--J   <-- br1
            /
...--F--G--H   <-- main
            \
             K--L   <-- br2

the whole thing rapidly becomes a nightmare of history rewriting, with the need to move multiple branch names. You can do this using git filter-branch or git filter-repo, but it's painful and not something you want to do frequently. This is where git replace comes in.


1If the key used to retrieve the object, compared to the hash of the object, does not match, something happened to the data since they were originally written. The hash function is of no help in correcting the erroneous data, so at this point we're stuck with finding a good copy, presumably in another clone or a backup. That's why disk drives use, e.g., Reed-Solomon codes rather than cryptographic checksums. Git's job here is only to find corruption, not to fix it.

2This "eventually" is a maintenance operation. The newfangled git maintenance command can be used to tune this stuff—that's the future direction for Git—but the actual dropping is done via git gc or git gc --auto, in existing Git usage. That works as follows:

  • git gc runs git reflog expire.
  • git reflog scans reflogs, which contain reflog entries.
  • The reflog entries each have a date-and-time stamp, and a status ("reachable" or "unreachable") implied by the current hash ID stored in the corresponding ref.
  • The status leads git reflog expire to one of two "expiry" values: reachable, for commits reachable from the current ref value, and unreachable, for commits not reachable this way.
  • If the age of the entry exceeds the expiry value—30 days for "unreachable", by default—the reflog entry is deleted.

This drops the last actual reference to the internal Git commit object, which can now be deleted via git prune, which git gc runs after git reflog expire. So, running git commit --amend right after git commit pushes the "amended" commit off to the side, where it lingers for a minimum of 30 days thanks to reflog entries: one in the HEAD reflog and one in the branch reflog. Once the reflog entries are gone, there really is no reference to the commit, and git prune will prune it.


Replacements

The mechanism Git uses for replacements is simple. There's a relatively low level routine in Git to obtain an object from the objects database—that key-value store I mentioned earlier, where the keys are hash IDs and the values are objects. You give the key to the database lookup code and it fishes out the value.

Now, if you allow replacements—there are control knobs for this, at this level—then when you call the "get me an object, I have its hash ID" function, the lookup function will check to see if the object's hash ID exists as a name in the refs/replace/ namespace.

So: we can make a replacement commit F' that is a new and improved version of F. This commit has a hash ID, once we've written it to the object database. Let's say F had hash ID aaaaaaa, and F' has hash ID bbbbbbb (I've shortened them from 40 characters to 7 to make them easier to deal with, and real hash IDs are of course random looking).

We now store the hash ID bbbbbbb under the name refs/replace/aaaaaaa. That is, the hash ID of commit F, whatever it is, becomes a refs/replace/ name. In that name we store the hash ID of the replacement commit, here bbbbbbb.

When some other piece of Git software calls the "look up object" function with hash ID aaaaaaa, that software notices that refs/replace/aaaaaaa exists. That software reads the hash ID stored in refs/replace/aaaaaaa and, instead of looking up (and error-checking) aaaaaaa, it looks up (and error-checks) bbbbbbb instead. It then returns the replacement object's content, instead of the original object's content.

This means that when git log or git checkout or any other Git command goes to use commit F, it gets commit F' instead. Hence we've successfully replaced commit F without actually changing commit F.3 The git log command in particular makes sure to notice that this happened (the lookup routine will set a flag for git log to see) and adds the replaced notation that you saw.


3Note that this makes git gc and git prune have to work harder, because object F is still referenced "for real", while F' is referenced via the refs/replace/ name. Fortunately it suffices for git gc to run with replacements disabled.


看到現實,以及為什么這很重要

如果您想查看資料庫中真實內容,無需替換,您可以運行git --no-replace-objects log. 這將git log呼叫禁用替換的“獲取物件”函式您將看到原始歷史記錄,而不是被替換的歷史記錄。

要查看替換物件,請使用git replace --list(或git replace不帶引數,即--list),或在軟體中使用git for-each-ref refs/replace

請注意,當你克隆一個倉庫,在克隆程序通常不復制refs/replace/命名空間。默認情況下,使用git push也不會復制refs/replace/名稱。因此,當您使用git replace您的存盤庫中構建虛幻的歷史時,這只會影響您的存盤庫

您也可以替換非提交物件。因為替換是一個如此低級的操作,您可以將其用于各種有趣的效果。但它始終是本地的,除非您采取特殊措施將refs/replace/參考也放入另一個存盤庫。

請注意,使用git filter-branchgit filter-repo將使具有替換存盤庫受到尊重(盡管git --no-replace-objects filter-branch不會,并且可能與 有類似的事情filter-repo)。因此,一種用途git replace是編輯歷史記錄,直到它看起來像您希望其他人看到的那樣。然后,您運行其他無操作過濾器操作,它“將新的歷史記錄固定到位”,無需替換(它們現在已嵌入,而原件已消失)。然后您發布這個新的、不同的存盤庫而不是原始存盤庫

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

標籤:混帐 版本控制 git-log

上一篇:將一個分支的提交重定位到另一個分支

下一篇:如何同步不同存盤庫中的兩個分支

標籤雲
其他(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)

熱門瀏覽
  • CA和證書

    1、在 CentOS7 中使用 gpg 創建 RSA 非對稱密鑰對 gpg --gen-key #Centos上生成公鑰/密鑰對(存放在家目錄.gnupg/) 2、將 CentOS7 匯出的公鑰,拷貝到 CentOS8 中,在 CentOS8 中使用 CentOS7 的公鑰加密一個檔案 gpg -a ......

    uj5u.com 2020-09-10 00:09:53 more
  • Kubernetes K8S之資源控制器Job和CronJob詳解

    Kubernetes的資源控制器Job和CronJob詳解與示例 ......

    uj5u.com 2020-09-10 00:10:45 more
  • VMware下安裝CentOS

    VMware下安裝CentOS 一、軟硬體準備 1 Centos鏡像準備 1.1 CentOS鏡像下載地址 下載地址 1.2 CentOS鏡像下載程序 點擊下載地址進入如下圖的網站,選擇需要下載的版本,這里選擇的是Centos8,點擊如圖所示。 決定選擇Centos8后,選擇想要的鏡像源進行下載,此 ......

    uj5u.com 2020-09-10 00:12:10 more
  • 如何使用Grep命令查找多個字串

    如何使用Grep 命令查找多個字串 大家好,我是良許! 今天向大家介紹一個非常有用的技巧,那就是使用 grep 命令查找多個字串。 簡單介紹一下,grep 命令可以理解為是一個功能強大的命令列工具,可以用它在一個或多個輸入檔案中搜索與正則運算式相匹配的文本,然后再將每個匹配的文本用標準輸出的格式 ......

    uj5u.com 2020-09-10 00:12:28 more
  • git配置http代理

    git配置http代理 經常遇到克隆 github 慢的問題,這里記錄一下幾種配置 git 代理的方法,解決 clone github 過慢。 目錄 git配置代理 git單獨配置github代理 git配置全域代理 配置終端環境變數 git配置代理 主要使用 git config 命令 git單獨 ......

    uj5u.com 2020-09-10 00:12:33 more
  • Linux npm install 裝包時提示Error EACCES permission denied解

    npm install 裝包時提示Error EACCES permission denied解決辦法 ......

    uj5u.com 2020-09-10 00:12:53 more
  • Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包

    Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包。 18 (flaskApi) [root@67 flaskDemo]# yum -y install nginx 19 已加載插件:fastestmirror, langpacks 20 Loading ......

    uj5u.com 2020-09-10 00:13:13 more
  • Linux查看服務器暴力破解ssh IP

    在公網的服務器上經常遇到別人爆破你服務器的22埠,用來挖礦或者干其他嘿嘿嘿的事情~ 這種情況下正確的做法是: 修改默認ssh的22埠 使用設定密鑰登錄或者白名單ip登錄 建議服務器密碼為復雜密碼 創建普通用戶登錄服務器(root權限過大) 建立堡壘機,實作統一管理服務器 統計爆破IP [root ......

    uj5u.com 2020-09-10 00:13:17 more
  • CentOS 7系統常見快捷鍵操作方式

    Linux系統中一些常見的快捷方式,可有效提高操作效率,在某些時刻也能避免操作失誤帶來的問題。 ......

    uj5u.com 2020-09-10 00:13:31 more
  • CentOS 7作業系統目錄結構介紹

    作業系統存在著大量的資料檔案資訊,相應檔案資訊會存在于系統相應目錄中,為了更好的管理資料資訊,會將系統進行一些目錄規劃,不同目錄存放不同的資源。 ......

    uj5u.com 2020-09-10 00:13:35 more
最新发布
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:43:21 more
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:42:36 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:26:53 more
  • 設定Windows主機的瀏覽器為wls2的默認瀏覽器

    這里以Chrome為例。 1. 準備作業 wsl是可以使用Windows主機上安裝的exe程式,出于安全考慮,默認情況下改功能是無法使用。要使用的話,終端需要以管理員權限啟動。 我這里以Windows Terminal為例,介紹如何默認使用管理員權限打開終端,具體操作如下圖所示: 2. 操作 wsl ......

    uj5u.com 2023-04-19 09:25:49 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:19:04 more
  • Linux學習筆記

    IP地址和主機名 IP地址 ifconfig可以用來查詢本機的IP地址,如果不能使用,可以通過install net-tools安裝。 Centos系統下ens33表示主網卡;inet后表示IP地址;lo表示本地回環網卡; 127.0.0.1表示代指本機;0.0.0.0可以用于代指本機,同時在放行設 ......

    uj5u.com 2023-04-18 06:52:01 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:50 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:01 more
  • 你是不是暴露了?

    作者:袁首京 原創文章,轉載時請保留此宣告,并給出原文連接。 如果您是計算機相關從業人員,那么應該經歷不止一次網路安全專項檢查了,你肯定是收到過資訊系統技術檢測報告,要求你加強風險監測,確保你提供的系統服務堅實可靠了。 沒檢測到問題還好,檢測到問題的話,有些處理起來還是挺麻煩的,尤其是線上正在運行的 ......

    uj5u.com 2023-04-05 16:52:56 more
  • 細節拉滿,80 張圖帶你一步一步推演 slab 記憶體池的設計與實作

    1. 前文回顧 在之前的幾篇記憶體管理系列文章中,筆者帶大家從宏觀角度完整地梳理了一遍 Linux 記憶體分配的整個鏈路,本文的主題依然是記憶體分配,這一次我們會從微觀的角度來探秘一下 Linux 內核中用于零散小記憶體塊分配的記憶體池 —— slab 分配器。 在本小節中,筆者還是按照以往的風格先帶大家簡單 ......

    uj5u.com 2023-04-05 16:44:11 more