Isomorphic-git: git commit --amend

Created on 5 May 2019  路  4Comments  路  Source: isomorphic-git/isomorphic-git

I'm working on my new project using isomorphic git as history of save in editor. I'm in process of writing the app and I've added first commit but with wrong author It would be nice to have amend option that would modify existing commit. I can just trash whole git repo it just single commit nad new repo, but want to know if something like this exists in Isomorphic-git.

Or is there a way to have amend like functionally by editing files in .git directory?

enhancement

Most helpful comment

It seems that I have git reset in code of my git terminal, thanks will use reset then. Here is my reset function if someone would be interested:

async function gitReset({git, dir, ref, branch, hard = false}) {
    var re = /^HEAD~([0-9]+)$/;
    var m = ref.match(re);
    if (m) {
        var count = +m[1];
        var commits = await git.log({dir, depth: count + 1});
        return new Promise((resolve, reject) => {
            if (commits.length < count + 1) {
                return reject('Not enough commits');
            }
            var commit = commits.pop().oid;
            fs.writeFile(`${dir}/.git/refs/heads/${branch}`, commit + '\n', (err) => {
                if (err) {
                    return reject(err);
                }
                if (!hard) {
                    resolve();
                } else {
                    // clear the index (if any)
                    fs.unlink(`${dir}/.git/index`, (err) => {
                        if (err) {
                            return reject(err);
                        }
                        // checkout the branch into the working tree
                        git.checkout({ dir, ref: branch }).then(resolve);
                    });
                }
            });
        });
    }
    return Promise.reject(`Wrong ref ${ref}`);
}

it's my old code that use fs with callbacks.

And my code that use this function look like this:

                const hard = cmd.args.includes('--hard');
                try {
                    var dir = await gitroot(cwd);
                    const ref = cmd.args.filter(arg => arg.match(/^HEAD/))[0];
                    if (ref) {
                        await gitReset({dir, git: git_wrapper, hard, ref, branch});
                        const commits = await git.log({dir, depth: 1});
                        const commit = commits.pop();
                        const head = await git.resolveRef({dir, ref: 'HEAD'});
                        term.echo(`HEAD is now at ${commit.oid.substring(0, 7)} ${commit.message.trim()}`);
                    }
                } catch(e) {
                    term.exception(e);
                } finally {
                    term.resume();
                }

and if I would need this in my terminal there also would be need to call git add if used with

git commit --amed -am 'new message'

When I will have wroking commit amend will add the code. The working code can be put into FAQ.

All 4 comments

In this particular case, where you want to amend the very first commit, you could probably get away with simply deleting .git/refs/heads/master and re-running git.commit.

If it's _not_ the very first commit, modifying the current branch to point to the previous commit would work. (git.commit adds a new commit object whose parent is whatever 'HEAD' resolves to.)

I like the idea of adding an amend command to isomorphic-git so I'll lay out the feature specifications here for reference. (I think it would be simpler to implement as a new command rather than as an option to the commit command.)

To properly implement git commit --amend we would need to:

  1. resolve 'HEAD'
  2. read the commit object
  3. overwrite fields like message or author.name
  4. update author and committer timestamp? // if canonical git does
  5. write the commit object
  6. update the current branch pointer

It seems that I have git reset in code of my git terminal, thanks will use reset then. Here is my reset function if someone would be interested:

async function gitReset({git, dir, ref, branch, hard = false}) {
    var re = /^HEAD~([0-9]+)$/;
    var m = ref.match(re);
    if (m) {
        var count = +m[1];
        var commits = await git.log({dir, depth: count + 1});
        return new Promise((resolve, reject) => {
            if (commits.length < count + 1) {
                return reject('Not enough commits');
            }
            var commit = commits.pop().oid;
            fs.writeFile(`${dir}/.git/refs/heads/${branch}`, commit + '\n', (err) => {
                if (err) {
                    return reject(err);
                }
                if (!hard) {
                    resolve();
                } else {
                    // clear the index (if any)
                    fs.unlink(`${dir}/.git/index`, (err) => {
                        if (err) {
                            return reject(err);
                        }
                        // checkout the branch into the working tree
                        git.checkout({ dir, ref: branch }).then(resolve);
                    });
                }
            });
        });
    }
    return Promise.reject(`Wrong ref ${ref}`);
}

it's my old code that use fs with callbacks.

And my code that use this function look like this:

                const hard = cmd.args.includes('--hard');
                try {
                    var dir = await gitroot(cwd);
                    const ref = cmd.args.filter(arg => arg.match(/^HEAD/))[0];
                    if (ref) {
                        await gitReset({dir, git: git_wrapper, hard, ref, branch});
                        const commits = await git.log({dir, depth: 1});
                        const commit = commits.pop();
                        const head = await git.resolveRef({dir, ref: 'HEAD'});
                        term.echo(`HEAD is now at ${commit.oid.substring(0, 7)} ${commit.message.trim()}`);
                    }
                } catch(e) {
                    term.exception(e);
                } finally {
                    term.resume();
                }

and if I would need this in my terminal there also would be need to call git add if used with

git commit --amed -am 'new message'

When I will have wroking commit amend will add the code. The working code can be put into FAQ.

I was using @jcubic's getReset function in TypeScript and modified it a tiny bit, in case it's useful to anyone until it lands鈥攊t also takes in pfs as an argument because of my usecase:

type GitResetArgs = {
  pfs: any,
  git: any,
  dir: string,
  ref: string,
  branch: string,
  hard?: boolean
};
async function gitReset({pfs, git, dir, ref, branch, hard = false}: GitResetArgs) {
  const re = /^HEAD~([0-9]+)$/;
  const m = ref.match(re);
  if (!m) { throw new Error(`Wrong ref ${ref}`) }
  const count = +m[1];
  const commits = await git.log({dir, depth: count + 1});
  if (commits.length < count + 1) { throw new Error('Not enough commits'); }
  const commit: string = commits[commits.length - 1].oid;
  await pfs.writeFile(`${dir}/.git/refs/heads/${branch}`, commit + '\n');
  if (!hard) { return }
  // clear the index (if any)
  await pfs.unlink(`${dir}/.git/index`);
  // checkout the branch into the working tree
  git.checkout({dir, ref: branch});
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

creationix picture creationix  路  4Comments

wmhilton picture wmhilton  路  6Comments

juancampa picture juancampa  路  6Comments

krasimir picture krasimir  路  3Comments

juancampa picture juancampa  路  7Comments