git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Bug Report: notes disassociated after history edits

From
Jeff King <peff@peff.net>
Date
Aug 23, 2019, 05:59 UTC
Message-ID
<20190823055932.GA10806@sigill.intra.peff.net>
In-Reply-To
<01F35983-BC98-4518-8ED3-C0E1AFC7507A@mac.com>
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 --stdin
Hope that helps.
-Peff
Previous: Christopher Sean MorrisonNext: Junio C Hamano
Message 2 of 3 in “Bug Report: notes disassociated after history edits”
  1. Christopher Sean MorrisonAug 22, 2019
  2. Jeff KingAug 23, 2019
  3. Junio C HamanoAug 23, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.