Re: Bug Report: notes disassociated after history edits
On Thu, Aug 22, 2019 at 04:44:37PM -0400, Christopher Sean Morrison wrote:
Show 15 quoted lines
> We’re migrating a very large old repository to Git (the oldest in
> continuous development!) and using the notes feature to preserve Svn
> data like revision IDs and branch information. We’ve run into what
> seems like an incomplete feature or bug in that notes get
> orphaned/disassociated if an old commit is changed (e.g., edit a
> committer's e-mail or the commit message).
>
> The changed commit and all children commits get sha updates, but the
> notes remain associated with the original sha. This can be
> particularly catastrophic, for example, if an early commit is changed
> as all notes become orphaned.
>
> I presume this is a bug but perhaps we may be doing something wrong?
> Is there a better way to preserve old Svn information that will work
> with filter-branch?
Whether the old notes apply to the rewritten commit depends on what is in the notes. Commands like rebase and "commit --amend" that rewrite history have some options to carry notes across rewrites. See "notes.rewrite*" in "git help config".
I don't think that filter-branch ever learned about rewriting notes. Here's an old thread asking the same thing:
https://public-inbox.org/git/hbf.20110317iwua@bombur.uio.no/
And it even mentions an even more ancient patch:
https://public-inbox.org/git/0ad4b8c1a5377d697513cd8e49f64419cd8deef4.1266164150.git.trast@student.ethz.ch/
The consensus seems to be that filter-branch should actually have a notes filter, but nobody ever implemented it.
In the meantime, I think you could accomplish the same thing with a --commit-filter. This seems to work for me:
# fake repo with some notes
git init repo
cd repo
for i in 1 2 3; do
echo $i >orig-$i
git add orig-$i
git commit -m $i
git notes add -m "note $i"
done
# introduce a silly tree change that will modify the commit ids,
# and map the notes, too
git filter-branch \
--tree-filter 'rename s/orig-/new-/ *' \
--commit-filter '
commit=$(git commit-tree "$@")
git notes copy $GIT_COMMIT $commit
echo $commit
'
# this should have the new-* files, but still have notes
git log --raw
I think you could also use "--state-branch", and then pass its mapping into a single "notes copy" invocation, which would be much more efficient. E.g.:
git filter-branch \
--tree-filter 'rename s/orig-/new-/ *' \
--state-branch refs/mapped-state
git cat-file blob refs/mapped-state:filter.map |
tr ':' ' ' |
git notes copy --stdinHope that helps.
-Peff