Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect git replace #826

Open
1 task done
muja opened this issue Aug 29, 2024 · 11 comments
Open
1 task done

Respect git replace #826

muja opened this issue Aug 29, 2024 · 11 comments
Assignees
Labels
bug Something isn't working

Comments

@muja
Copy link

muja commented Aug 29, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Description of the bug

When editing a commit message with git replace --edit <commit-sha1>, git cliff keeps displaying the message of the old commit. It should instead display the message of the new commit that replaced the old one. More info about git replace

Steps To Reproduce

cd $(mktemp -d)
git init .
git commit --allow-empty -m 'feat: initial commit'
git replace --edit HEAD # change type to chore
# e.g. vim: 4jcwchore<ESC>:wq
git cliff --unreleased

Expected behavior

Changelog

All notable changes to this project will be documented in this file.

[unreleased]

Miscellaneous Tasks

  • Initial commit

Screenshots / Logs

No response

Software information

  • Project version: 2.4.0

Additional context

No response

@muja muja added the bug Something isn't working label Aug 29, 2024
Copy link

welcome bot commented Aug 29, 2024

Thanks for opening your first issue at git-cliff! Be sure to follow the issue template! ⛰️

@orhun
Copy link
Owner

orhun commented Aug 30, 2024

Hello, thanks for reporting!

git-cliff uses git2 to query the commit information from the repo. So I'm not sure what's going on there - also, I'm not familiar with git replace. Are you using it to edit the commit messages? If so, why not amend?

Maybe @alerque knows something about this, since I think he's more of a Git guru than I am.

@alerque
Copy link
Contributor

alerque commented Aug 30, 2024

Using git commit --amend or other flavors of rewriting (git rebase, git revise, etc.) all fundamentally reflow the history too. Taking A -> B -> C and rewriting the message for B will also make C into a different commit: A -> B' -> C'. I haven't used it much, but I believe git relpace works differently by keeping a table on the side of objects swaps to make. Editing the commit message of B that way keeps C as it's original commit, but when the log is queried there is effectively a hot-swap being made for the object: A -> B (but show as B') -> C. C is still based on B and the original hashes are still accessible, but every time B is queried tooling that supports it notices in the lookup table that their is a replacement for it. As such the history isn't changed, but tooling has to support the extra step to check for replacements of all objects.

I expect that libgit2 does support this already, but that one would have to explicitly query for it all the time since it is a side car along for the ride not the bike—it's a kind of filter-on-use rather than the actual history being changed. When you look at the git log of the three commits in the example above, the sha hash of B will be unchanged, but will read <hash> (replaced) instead of <hash>. Presumably an extra lookup query needs to happen for every object used to get the replacements (if any).

@muja
Copy link
Author

muja commented Aug 30, 2024

Are you using it to edit the commit messages? If so, why not amend?

amend changes the history, replace does not. I want to reword some commits on master to change the respective item in the release notes without changing the history. I have also asked whether that is possible in some other way.

@alerque
Copy link
Contributor

alerque commented Aug 30, 2024

whether that is possible in some other way

Yes, git cliff can filter the commits in several ways while processing them for the changelog. If the changelog is the only place your are worried about them being replaced I would suggest looking into them, although I do think using git replace should work and has the advantage of showing up in other places besides the changelog (e.g. git log).

See commit_preprocessors for one way. For example I apply spelling fixes to changelogs even when history has typos like this:

commit_preprocessors = [
  { pattern = '.*', replace_command = 'typos --quiet --write-changes -' },
]

There are also mechanisms including a JSON dump you can process yourself.

@orhun
Copy link
Owner

orhun commented Sep 1, 2024

Reported to git2: rust-lang/git2-rs#1081

Meanwhile this reminds me of #131 which should happen sometime.

@alerque
Copy link
Contributor

alerque commented Sep 1, 2024

Upstream libgit2 issue has been open for 11 years‽ Yah it might be time to give gitoxide a shake.

@muja
Copy link
Author

muja commented Sep 1, 2024

FWIW, how sensible would it be do to manual parsing of the files in .git/refs/replace?
The structure seems straight forward, the replacements are <filename> -> <content>, e.g. file foo with content bar means "foo was replaced by bar". One thing to note is that transitive replaces are supported

@orhun
Copy link
Owner

orhun commented Sep 1, 2024

That might be a bit of work that is outside of git-cliff's scope. It would probably be better to offload it to another library and bring it to git-cliff that way.

Can't say something certain without seeing the implementation though.

@alerque
Copy link
Contributor

alerque commented Sep 1, 2024

how sensible would it be do to manual parsing of the files in .git/refs

Somewhere north of "crazy pants" but not all the way to "maniac yolo on meth". Just don't. Even if the actual format is pretty stable unless you are in the business of monkeying with Git internals there are too many things that can go sideways. Starting (but by no means ending) with that stuff may or may not be in a .git directory at all. Git cliff uses Git through a library and I think it should stick to the API surface of the library. As long as that is libgit2 it looks like this is stalled. If it were to be ported to gitoxide I suppose that would be an open question again. I don't know if it supports that feature yet. Or you could be really brave and try to get this worked out in libgit2 upstream.

@muja
Copy link
Author

muja commented Sep 2, 2024

According to the docs, gitoxide support replace:

object replacements are read once upon opening the repository from their refs and changes to these won't be picked up.

in SHORTCOMINGS.md

however I have no idea how to verify it, gix log doesn't exist and I have no idea how to use the lib

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants