Git notes after bfg?

I switched from SVN to git and I had a note in every git declaration referring to the SVN version number. After importing the repo, I used the BFG repository cleaner to clear the git history from binaries and other garbage. Unfortunately, now I do not see notes when I type git log . I suppose the BFG forgets to update note commit commits. BFG leaves a * .txt message with the mapping of the identifier of the old object to the new object identifier in the following format:

 0001b24011381e8885683cd1119ba4cb077fa64b c81149b1b52b9e1e1767d6141f292891d715edb5 00024eecdc31f2f6e67018f7d6f00e7c1ad03f1f 326ee3b508e3dd2934ec1f50069195f86ea1a1c7 00028e04dcc2d59bd835b447bd3a207ae481696c 3d18e9b9d3336e59d62093200b81603ffefcc747 

Can you suggest a few scripts to quickly fix notes based on the above display?

PS: I'm pretty sure that the problem is caused by non-updated refs, because when I type git notes , in second place I can see links that are considered old in BFG repot object-id-map.old-new.txt

+7
source share
2 answers

I wrote the following bash script to transfer my notes from old objects. The solution is slow in a single thread, not sure if you can run multiple git notes commands in parallel.

 while read string; do hashesArray=($string) git notes copy ${hashesArray[0]} ${hashesArray[1]} git notes remove --ignore-missing ${hashesArray[0]} done <object-id-map.old-new.txt 
+4
source

[ Edit : Git version 2.15 released in November 2017 added --state-branch to the filter branch. This option saves the map in a file in branches, which the first operation of the filter branch creates. Subsequent filter branch operations will use the existing map. So, starting with Git 2.15, add --state-branch <name> to your filter branch operation, then use the map in the newly created branch.]

There is nothing built in to do this; You will have to write a script or program yourself. On the other hand, BFG left you a map file: it is much better than the git filter-branch that throws it away, so the information needed to update notes has disappeared.

The basic implementation in the notes is that refs/notes/commits (or what you set for core.notesRef ) points to a regular commit, which you can at least theoretically git checkout (maybe in a temporary work tree, which you created specifically for this purpose). This tree contains files whose names are annotated commits - only slightly modified. For example, if:

 0001b24011381e8885683cd1119ba4cb077fa64b c81149b1b52b9e1e1767d6141f292891d715edb5 

is a recording entry, where 0001b24011381e8885683cd1119ba4cb077fa64b is the old commit, and if 0001b24011381e8885683cd1119ba4cb077fa64b has a note record, there will be a file named 00/01b2...

The nesting depth of all these added subdirectories is dynamically controlled by the note code, with the general idea being to "add as many trees as needed to quickly find if there is a note, but not so many trees to occupy a lot." storage space when there are very few notes starting with 0001b2... This fork is not critical to your goals, although you might want to keep it for the same reasons of speed.

Your task is to find each file in this tree under its old name and move (or copy) it to a new name corresponding to the new commit identifier. Since in this case the new name will be c81149b1b52b9e1e1767d6141f292891d715edb5 , you will rename the file to c8/1149b1b52b9e1e1767d6141f292891d715edb5 , or c8/11/49b1b52b9e1e1767d6141f292891d715edb5 After you rename all the files (via index: use git mv or git rm --cached ). and git add if necessary), you can turn them into a regular commit object using git write-tree followed by git commit-tree . Make the parent of the new commit the existing commit refs/notes/commits and use git update-ref to update the refs/notes/commits so that it points to the new commit and your notes should appear again after filtering.

(If you have such a thing, it would be nice to join it with git filter-branch and / or BFG itself.)

0
source

Source: https://habr.com/ru/post/1260080/


All Articles