"Co-authored-by" trailer - #57
Conversation
If the environment variable GIT_DUET_CO_AUTHORED_BY is set to 1, there will be a "Co-authored-by" trailer added for each co-author instead of a "Signed-off-by" trailer for the committer. This gives every contributor attribution in Github's contribution graph. Resolves git-duet#56.
|
Thanks for taking a crack at this @ansd ! I think what you have here is reasonable, but I'm wondering if we might be able to take this as an opportunity to simplify It would be a bit of a divergence from the current techniques the tool uses that utilize the The downsides are:
While I'm actually OK with the second one as I always viewed usage of the |
|
@jszwedko, thanks for your feedback. I like the idea of having the Open questions:
|
|
Thanks for putting together that example subcommand! That is very much along the lines of what I was thinking. With regards to your open questions:
Thanks again for engaging on this. |
|
@jszwedko It would be good to keep supporting the It would also be handy to keep existing functionality until use of |
Requires a prepare-commit-msg hook: #!/usr/bin/env bash exec git duet-prepare-commit-msg "$1"
|
@jszwedko, thanks for your answer. I gave it a try. The prepare-commit-msg hook file gets now installed when running Questions:
|
|
Good notes, @rafecolton, thanks for checking me. I agree that we should continue supporting the |
jszwedko
left a comment
There was a problem hiding this comment.
Overall this is looking great, thanks for all of your work on this @ansd
I think the remaining items are:
- Default
GIT_DUET_SET_GIT_USER_CONFIGwhenGIT_DUET_CO_AUTHORED_BYis set - Think a bit more about the various configuration settings users may have had set before setting
GIT_DUET_CO_AUTHORED_BY - Some manual testing to make sure we aren't missing any cases in the automated tests you added
As this is such a divergence from the normal workflow, I'm also thinking we could mark this feature as experimental in the README to set expectations and encourage people to report any issues they find (both bugs and usability).
Thanks again! 🎉 🎊
| os.Exit(1) | ||
| } | ||
| if committers == nil || len(committers) == 0 { | ||
| os.Exit(0) |
There was a problem hiding this comment.
This appears to be assuming GIT_DUET_CO_AUTHORED_BY implies GIT_DUET_SET_GIT_USER_CONFIG. I agree with this decision, but I think we'll need update to duet.Configuration to codify this (and maybe include this in the README).
There was a problem hiding this comment.
This also makes me realize we'll need to consider the various paths users might take opting in to this feature, e.g.:
git solo js # without GIT_DUET_SET_GIT_USER_CONFIG, so only sets `git-duet` specific configuration
export GIT_DUET_CO_AUTHORED_BY=1
git commit -m 'test' # will not use the author set by `git solo js`
I'll think about this a bit more.
There was a problem hiding this comment.
I think there is just a single path how users can opt in, namely by running git duet with GIT_DUET_CO_AUTHORED_BY set.
I think in your above example, it's okay that the commit doesn't set js as author since the user didn't run git solo with either GIT_DUET_SET_GIT_USER_CONFIG or GIT_DUET_CO_AUTHORED_BY (the latter implicitly setting GIT_DUET_SET_GIT_USER_CONFIG).
There was a problem hiding this comment.
Right, I'm just thinking that people might have an expectation, in my example, that GIT_DUET_CO_AUTHORED_BY would pick up the previous git solo even without GIT_DUET_SET_USER_CONFIG. I'm willing to concede that it feels likely that users will set that variable and then call git duet though.
|
|
||
| contents := strings.TrimSpace(string(b)) | ||
| if contents != "" { | ||
| if hook == preCommitHook && contents != strings.TrimSpace(preCommitHook) || |
There was a problem hiding this comment.
I'm concerned that this doesn't allow for future versions of git-duet to overwrite with updated hook contents.
There was a problem hiding this comment.
However, this should be rare and I think we can address it if it comes up by including an index of previous hook contents for comparison (or hashes) so I'm OK with this as-is.
|
@jszwedko, concerning the remaining items:
Thank you for reviewing the code :) |
| printNextComitter(committers) | ||
| if configuration.CoAuthoredBy { | ||
| installPrepareCommitMsgHook() | ||
| if err = gitConfig.SetAuthor(author); err != nil { |
There was a problem hiding this comment.
Can you clarify why this is needed? It wasn't immediately apparent to me (maybe a comment here would help).
There was a problem hiding this comment.
This is needed for the case that the user runs GIT_DUET_CO_AUTHORED_BY=1 git duet without args (author initials) and without having set GIT_DUET_SET_GIT_USER_CONFIG in previous git duet commands. If the above line is missing, this test will fail. I will add a comment for this.
The basic question is whether running git duet without args (author initials) should install the hook (and set the author like above) or should it be just a "getter" like it always has been which merely prints the current author and committer?
|
Fantastic, thanks @ansd . I appreciate you adding the additional tests and changes. I think that, for the |
When interactively rebasing or cherry-picking, the prepare-commit-msg hook gets called. Previously, a Co-authored-by trailer has been appended. This change checks first if there is already a trailer, and if there is one, no further trailer will be added since rebasing and cherry-picking doesn't change authorship. Current drawbacks: - if the commit being rebased doesn't have a trailer, a new trailer will still be appended - git commit --amend will not append new trailers if there is already a trailer
Before this commit, "git commit --verbose" didn't append any trailers because the trailers were added after the comments and diff. The right place for the trailers block is before the start of the comments. This is easily achieved with the "git interpret-trailers" command.
|
@jszwedko, sure, that's a good idea. See changes above. Just to summarise: The goal for rebasing and cherry-picking is to not add any So, the only drawback for now is that a new Also, |
| as part of rebasing or cherry-picking, at the very least, it checks for existing trailers, | ||
| and if there is one, no new trailers will be appended. | ||
| Trailers will still be appended for "git commit --amend" in which case the | ||
| commitMsgSource's value is "commit". */ |
| err = ioutil.WriteFile(commitMsgFile, []byte(fmt.Sprintf("%s\n%s", string(commitMsg), coAuthorsTrailer)), 0644) | ||
| for _, c := range committers { | ||
| trailer := "Co-authored-by: " + c.Name + " <" + c.Email + ">" | ||
| cmd := exec.Command("git", "interpret-trailers", "--in-place", "--trailer", trailer, commitMsgFile) |
There was a problem hiding this comment.
I also just saw it by coincidence looking at the prepare-commit-msg.sample file :)
| } | ||
|
|
||
| // override the default "addIfDifferentNeighbor" so that no duplicate trailers will get appended | ||
| err = gitConfig.SetUnnamespacedKey("trailer.ifexists", "addIfDifferent") |
There was a problem hiding this comment.
I think setting this un-namespaced variable here might cause some slight confusion to people already depending on a different behavior. I admit it's probably pretty rare, but what do you think, rather than setting this here, we just document that you can set this value to avoid duplicate Co-authored-by:s for the same author?
There was a problem hiding this comment.
Right, makes sense. I removed this part from the hook and wrote it into the README so that the user can optionally set it.
| } | ||
|
|
||
| func (gc *GitConfig) getKey(key string) (value string, err error) { | ||
| func (gc *GitConfig) SetUnnamespacedKey(key, value string) (err error) { |
There was a problem hiding this comment.
I think, if we decide to keep the setting of the trailer config above, I'd prefer to see that exposed as a new method that abstracts away how it is setting the value (e.g. what you have for SetInitTemplateDir) rather than exposing this method.
There was a problem hiding this comment.
True, that would have been better! I reverted the changes to this file to the previous commit since we decide to not set trailer.ifexists in the hook.
|
Hi @ansd, Thanks for your continued work on this! I really appreciate it. I left a couple of comments in-line. I really like the change to using 🎆 |
Rather than having the prepare-commit-msg hook set this variable's value to `addIfDifferent`, let the user set it manually (just in case they already depend on different behaviour).
|
Hi @jszwedko, thanks for your comments. I removed setting the |
| When amending a commit and the co-author has changed, a new `Co-authored-by` trailer will get appended for | ||
| that co-author. In order to avoid duplicate `Co-authored-by` trailers (i.e. trailers with the same co-author), | ||
| set `git config [--global] trailer.ifexists addIfDifferent` to override the default value `addIfDifferentNeighbor`. | ||
|
|
|
Looks great! Thanks again for all of your hard work @ansd . I think this is ready to merge. |
|
Released as 0.6.0 🎉 🎺 |
This is a proposal of how the co-authored-by trailer could be implemented. It is configurable via the
GIT_DUET_CO_AUTHORED_BYenvironment variable.Basically, the last commit gets amended by appending the co-authored-by trailer for each contributor. Not sure if there are better ways to do it?