On Thu, Aug 22, 2019 at 04:44:37PM -0400, Christopher Sean Morrison wrote: > 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@xxxxxxxxxxxxx/ And it even mentions an even more ancient patch: https://public-inbox.org/git/0ad4b8c1a5377d697513cd8e49f64419cd8deef4.1266164150.git.trast@xxxxxxxxxxxxxxx/ 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 --stdin Hope that helps. -Peff