簡體   English   中英

Git 記錄 2 個標簽並過濾特定路徑的提交

[英]Git log 2 tags and filter commits for a particular path

我有一個包含許多不同文件夾和標簽的存儲庫。 我想列出特定文件夾的 2 個發布標簽之間的提交。

我試過git log --oneline -- ${folder path} tag1 tag2它似乎只過濾到指定文件夾路徑中的提交,但它似乎顯示的提交比標簽 1 和標簽 2 之間的差異更多。

有沒有辦法列出特定指定文件夾路徑的 2 個不同標簽之間的提交?

這里有很多問題:

  • --選項之后的所有內容都被視為文件名。 (例如,這使您可以查找名為master文件。)因此,此處的tag1tag2被視為文件名——它們不是指任何提交。 解決這個問題很容易,因為您只需將tag1和/或tag2移動到--的另一側。

  • 之間的整個概念很棘手,因為提交不一定都排在整齊的一排。 解決這個問題可能要困難得多:必須確定之間的含義。

  • 當您為git log提供路徑名稱時,這將啟用它所謂的歷史簡化 對於您的特定用途而言,這是否真的是一個問題也是一個難題,但如果它是一個問題,解決它實際上很容易:只需添加--full-history以禁用歷史簡化。

所以你可能想要:

git log --oneline --full-history <something with the tags> -- <folder-name>

僅當結果中似乎缺少某些提交時才需要--full-history

讓我們解決something

首先,請記住,Git 中的每個提交都包含所有文件的完整快照,以及有關該快照的一些元數據:誰制作了它(作者姓名,email,以及日期和時間戳加上相同的committer),一條日志消息,以及——對我們來說最重要的——一些先前提交的原始 hash ID,Git 將其稱為此提交的級或級。

每個提交都有一個獨特的、又大又丑的 hash ID。 這實際上是提交的真實名稱。 所有其他名稱,無論是像master這樣的分支名稱、像v2.1這樣的標簽名稱,還是像HEAD~3這樣的相對名稱,都只是讓 Git 找到原始 hash ID 的一種方式。 同時,每個名稱(包括分支名稱和標簽名稱)僅包含一個hash ID。 當一個 hash ID 是一個特定的提交時, 1就是由分支或標簽命名的提交。 我們說名稱指向提交。

但由於提交包含提交 hash ID,因此提交指向提交。 事實上,這正是 Git 存儲庫中歷史的發生方式。 一個名稱——通常是像master這樣的分支名稱——通過持有其 hash ID 指向最后一次提交。 如果我們讓H代表實際的 hash ID,我們可以這樣畫:

              H   <-- master

同時,提交H包含其父提交的 hash ID。 我們稱其為G ,因此H指向G

          G <-H   <-- master

當然G有它自己的父級。 我們稱之為F ,它也有自己的父級,依此類推:

... <-F <-G <-H   <-- master

這是一個很好的簡單線性提交鏈。 如果存儲庫中只有八個提交,都像這樣連續排列,我們可以將它們繪制為:

A--B--C--D--E--F--G--H   <-- master

由於懶惰和缺乏角度方向的箭頭,我現在使用線條而不是箭頭來連接提交,但請記住它們實際上都是向后指向的箭頭。 我們可以使用內部箭頭將 go 從提交H返回A ,但不能從A轉發H

(提交A很特殊:作為某人的第一個提交,它不能有父提交,所以它沒有。Git 將此稱為根提交。每個非空 Git 存儲庫都有至少一個根提交。這就是當我們回顧歷史時,我們可以停止追溯。)

要將新提交添加到某個分支,Git 只需用指向當前提交的箭頭寫出新提交,然后將新提交的實際 hash ID 寫入分支名稱。 例如,從:

...--G   <-- master

至:

...--G--H   <-- master

Git 剛剛用父 hash G編寫了新的提交H ,然后將H的實際 hash 寫入名稱master

但 Git 的歷史往往不是這樣的線性。 人們創建新的分支,然后這些分支上進行新的提交,這會導致如下圖:

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

隨后有人可能會做git checkout master; git merge br1 git checkout master; git merge br1以將分支 1 重新合並到master中,這會產生:

          I--J   <-- br1
         /    \
...--G--H--L---M   <-- master
         \
          K   <-- br2

新的合並提交M指向L (作為它第一個父節點)J (作為它的第二個父節點)。

技巧問題:在哪個分支上提交H

答:實際上是在所有三個分支上。 Git 在這里很特別:許多版本控制系統保存提交是在哪個分支上進行的,而這就是提交所在的分支,永遠。 Git 不會將此信息保存在任何地方。 如果您可以從分支名稱指向的提交開始到達該提交,則該提交位於分支上。 因此,從master開始,我們可以在從L的一跳中返回H ,或者在添加M后從M的兩跳中返回 H 。 br1開始,我們可以分兩跳回到H :從J開始,go 到I ,然后是H br2我們 go K然后H 所以H所有三個分支上。


1分支名稱被限制為僅包含提交 hash ID,因此分支名稱自動指向提交。 標簽名稱的限制較少:它們可以直接指向提交,在這種情況下,Git 稱它們為輕量級標簽。 或者,他們可以指向一個標簽 object ,它有自己唯一的 hash ID。 然后標記 object 指向另一個對象(通常是提交),因此標記仍然指向提交,但通過標記 object 間接指向。 這就是您可以使用額外信息(例如發行說明或 GPG 簽名)制作帶注釋的標簽的方法。


之間很棘手

讓我們使用其中一種圖表並添加一些標簽名稱,它們像分支一樣指向特定的提交,但不一定位於分支的末尾 (特別是,一旦你創建了一個標簽名稱,你應該讓它永遠指向同一個提交,通過它的 hash ID。)所以我們可能有:

     tag:v0.7    tag:v0.8
        |           |
        v           v
...--G--H--I--M--N--O--P   <-- branch1
      \
       J--K--L   <-- branch2
          ^
          |
       tag:v0.9

哪些提交是“介於”標簽v0.7v0.8之間? 我想大多數人都會同意它是IMN ,或者可能HIMNO ,或者類似的東西。

但是:哪些提交是“介於”標簽v0.7v0.9之間? 哪些在v0.8v0.9之間? 我想很多人會不同意。

如果事實證明提交M實際上是一個合並,而不是常規提交,那么繪圖應該看起來像這樣:

     tag:v0.7     tag:v0.8
        |            |
        v            v
...--G--H--I---M--N--O--P   <-- branch1
      \       /
       J--K--L   <-- branch2
          ^
          |
       tag:v0.9

現在哪些提交在各個標簽“之間”?

Git 給你的東西——Git 給你的所有東西——是使用各種修飾符來遍歷實際圖形的能力。 Git 通過從結尾開始(例如,在像P這樣的提交處)並向工作,在它可以實際工作的唯一方向上,使用連接提交的那些向后指向的箭頭來做到這一點。

您提供給git log的任何分支或標簽名稱都算作以下之一:

  • 一個起點:一個你想要向后工作的提交,或者
  • 一個停止點:您希望 Git包括的提交,也不包括它的任何祖先

例如,假設我們有第一張圖:

     tag:v0.7    tag:v0.8
        |           |
        v           v
...--G--H--I--M--N--O--P   <-- branch1
      \
       J--K--L   <-- branch2

我們告訴 Git:P開始,但在L停止 顯然,從P開始實際上不會讓我們提交L ,因為我們 go PONMIHG等等。 但是,通過告訴 GitL處停止,我們真正的意思是L到達的任何提交處停止:所有LKJG等向后都是停止點。

我們可能用於P開始但在L停止的語法是:

branch2..branch1

這意味着branch1的尖端(即P )可到達的所有提交,不包括從branch2的尖端(即L )可到達的所有提交

相同的語法適用於標簽名稱。 實際上,它的工作方式完全相同:僅提及標簽名稱,如git log v0.8中,意味着將此標簽指向的提交視為起點 提到兩個標簽名稱,它們之間有兩個點,意味着將此標簽指向的提交視為停止點 所以:

v0.7..v0.8

將從O開始並在H停止。 這將排除提交H ,即它只會查看提交O ,然后是N ,然后是M ,然后是I

如果名稱v0.9指向提交Kv0.9..v0.8將查看以O開頭的提交並向后工作,直到它停止在G 0.90.8之后並不重要。 Git 根本沒有使用這些數字。 Git 專門使用圖表來包含或排除各種提交。

當圖表中有合並時,事情就會變得棘手。 在這里,您有時可能需要一個額外的標志--ancestry-path 但就像--full-history一樣,這開始變得有點復雜,所以我們可能應該到此為止。

不過,我忍不住要提到第三種選擇,因為有些人在說“介於”時會想要這個。 除了兩點語法stop..start ,還有一個三點語法。 這意味着可以從任一名稱訪問的所有提交,除了可從兩個名稱訪問的所有提交 也就是說,給定:

...--G--H--I--M--N--O--P   <-- branch1
      \
       J--K--L   <-- branch2

語法branch1...branch2表示提交HIMNOP提交JKL (但不是按此順序,因為 Git 必須向后工作)。 排除的提交從G開始並向后工作,因為G在兩個分支上。

你的語法幾乎是正確的。

要列出一系列提交,請使用tag1..tag2 ,並將所有提交放在--之前。 因此,您的命令應如下所示:

git log --oneline tag1..tag2 -- path

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM