Created
February 22, 2023 20:54
-
-
Save yardenshoham/463eb3aec62cc0ef909af13b8203d778 to your computer and use it in GitHub Desktop.
ChatGPT's suggestion for implementing `cherry-pick` in `isomorphic-git`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment