Open yardenshoham opened 1 year ago
Ok, do you want to contribute?
I wouldn't know how to implement this. Is there an official git reference or another implementation you usually port from?
AFIK You need to know git internals and implement them based on those and the behavior of canonical git. Note that this project doesn't have an original author that left the project, so none will write this code for you. Unless you will find someone that will do this for you.
ChatGPT suggested the following approach, is it a good starting point or way off track?
import { RepoPath, CommitObject, GitError, MergeOptions, MergeReport } from 'isomorphic-git';
import { getCommit, listCommits, merge } from 'isomorphic-git';
// The cherryPick function takes a repository path and a commit SHA as input, and applies the
// changes made in the specified commit to the current branch. The function first gets the commit
// object for the specified commit, and then finds the parent commit(s) to use as the merge base(s).
// It then sets up the merge options, with ours set to the current HEAD commit and theirs set to the
// specified commit. The fastForwardOnly and noUpdateBranch options are used to ensure that the
// merge only applies changes from the specified commit, and does not change the branch reference
// or allow non-fast-forward merges. The merge function is then called to perform the merge and
// generate a merge report, which is used to check for merge conflicts. If there are conflicts,
// a GitError is thrown with an appropriate error message. If the merge succeeds without conflicts,
// the commit function is called to create a new commit with the merged changes. The commit message
// is set to cherry-pick: <original commit message>, and the author and committer are set to the same
// as the original commit. The parents are set to the current HEAD commit and the specified commit,
// and the tree is set to the merge result returned by the merge report.
async function cherryPick(repoPath: RepoPath, commitSha: string): Promise<void> {
// Get the commit object to apply changes from
const commit: CommitObject = await getCommit({ fs, dir: repoPath, oid: commitSha });
// Find the parent commit(s) to use as the merge base(s)
const parentCommits = await listCommits({ fs, dir: repoPath, ref: 'HEAD' });
// Set up the merge options
const mergeOptions: MergeOptions = {
dir: repoPath,
ours: parentCommits[0],
theirs: commitSha,
fastForwardOnly: true,
noUpdateBranch: true,
};
// Merge the changes from the specified commit
const mergeReport: MergeReport = await merge({ fs, ...mergeOptions });
// Check for merge conflicts
if (mergeReport.conflicts.length > 0) {
throw new GitError(E.MergeNotSupportedFail, {
message: 'Cherry-pick failed due to merge conflicts.',
});
}
// Commit the merge changes with the cherry-pick message
const message = `cherry-pick: ${commit.message}`;
const author = { ...commit.author, timestamp: Math.floor(new Date().getTime() / 1000) };
await commit({
fs,
dir: repoPath,
message,
author,
committer: author,
parents: [parentCommits[0], commitSha],
tree: mergeReport.oid,
});
}
Sorry, I have no idea, you should try but it probably will require refactoring. But I think that cherry-pick is just a merge of one commit taken from one branch to the other branch, I'm not sure how though.
Since isomorphic-git has no analogue for revert
or rebase
or patch
this would probably require implementing one or all of those from scratch I'm afraid. Since cherry-pick
and rebase
are somewhat redundant it would probably make the most sense to implement rebase
which would also solve #189 and #1527.
If you wanted to implement this yourself I think the easiest way would be to study the code of src/commands/merge.js
and create a similar rebase
command that calls mergeTree(onto, commit1)
, mergeTree(commit1, commit2)
, etc. where onto
is the commit we are rebasing onto.
If you only need to cherry-pick one commit at a time however, a simpler approach would be to expose mergeTree
and you could manually merge the cherry-picked commit with the tip of your branch, then commit that to the repo.
It's possible to write this with the current API, I did so for a project. I'll check with my employer if I can contribute it, as it was written for work.
@mdreier-sap sorry I have no idea, but you can try the ChatGPT solution.
@jcubic I think Martin is saying that he already has a solution and is willing to contribute it, if permitted.
I thought that the first sentence was a question.
I think Martin is saying that he already has a solution and is willing to contribute it, if permitted.
This is correct
@mdreier-sap Were you able to get permission to post this? ~rebase would be very helpful for us as well!~
Edit: I though the implementation you were mentioning was rebase, no cherry-pick
Is this still a requirement? I can try the implementation if needed.
@IAmSSH the feature is missing so if you want to implement cherry-pick that would be great. Make sure that you will add unit tests for the new feature.
I think cherry-picking is very useful for automating backports (that's my use-case at least)