DEV Community

Alba Rincón
Alba Rincón

Posted on

How to easily add co-authors to you commits

Git mob allows to add co-authors to git commits in an easy way. You can follow these steps to configure it for any repo you want.

1. Install the tool ⚙️

npm i -g git-mob
Enter fullscreen mode Exit fullscreen mode

2. Create the co-authors file 📃

Create a file named .git-coauthors in your home directory with the following content:

{
  "coauthors": {
    "foo": {
      "name": "Foo"
      "email": "foo@company.com"
    },
    "bar": {
      "name": "Bar",
      "email": "bar@company.com"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The keys of each co-author object will be the ones you need to type when selecting your commit co-authors, so you can change them to whatever you prefer.

3. Create the git hook ⚓

git mob uses the git prepare-commit-msg hook to append the co-authors to the commit message. Choose one of the following options to configure it:

Option 1: Create the git prepare-commit-msg hook globally (for all repos)
Option 2: Create the git hook only for a specific repo
Option 3: Advanced case: make the git hook work alongside other prepare-commit-msg hooks


Option 1: Create the git prepare-commit-msg hook globally (for all repos)

Enable git templates:

git config --global init.templatedir '~/.git-templates'
Enter fullscreen mode Exit fullscreen mode

This tells git to copy everything in ~/.git-templates to your repo .git/ directory when you run git init.

Create the file .git-templates/hooks/prepare-commit-msg in your home folder

mkdir -p .git-templates/hooks && touch .git-templates/hooks/prepare-commit-msg
Enter fullscreen mode Exit fullscreen mode

with the following content:

#!/usr/bin/env node
let exec = require('child_process').exec,
    fs = require('fs');

const commitMessage = process.argv[2];
// expect .git/COMMIT_EDITMSG
if(/COMMIT_EDITMSG/g.test(commitMessage)){
    let contents = "";
    exec("git mob-print",
        function (err, stdout) {
        if(err) {
            process.exit(0);
        }

        // opens .git/COMMIT_EDITMSG
        contents = fs.readFileSync(commitMessage);

        if(contents.indexOf(stdout.trim()) !== -1) {
            process.exit(0);
        }

        const commentPos = contents.indexOf('# ');
        const gitMessage = contents.slice(0, commentPos);
        const gitComments = contents.slice(commentPos)

        fs.writeFileSync(commitMessage, gitMessage + stdout + gitComments);
        process.exit(0);
    });
}
Enter fullscreen mode Exit fullscreen mode

make it executable running:

chmod +x .git-templates/hooks/prepare-commit-msg
Enter fullscreen mode Exit fullscreen mode

and make it available in the repo you want by entering the repo folder and running:

git init
Enter fullscreen mode Exit fullscreen mode


Option 2: Create the git hook only for a specific repo

Create the file .git/hooks/prepare-commit-msg in your repo folder with the following content:

#!/usr/bin/env node
let exec = require('child_process').exec,
    fs = require('fs');

const commitMessage = process.argv[2];
// expect .git/COMMIT_EDITMSG
if(/COMMIT_EDITMSG/g.test(commitMessage)){
    let contents = "";
    exec("git mob-print",
        function (err, stdout) {
        if(err) {
            process.exit(0);
        }

        // opens .git/COMMIT_EDITMSG
        contents = fs.readFileSync(commitMessage);

        if(contents.indexOf(stdout.trim()) !== -1) {
            process.exit(0);
        }

        const commentPos = contents.indexOf('# ');
        const gitMessage = contents.slice(0, commentPos);
        const gitComments = contents.slice(commentPos)

        fs.writeFileSync(commitMessage, gitMessage + stdout + gitComments);
        process.exit(0);
    });
}
Enter fullscreen mode Exit fullscreen mode

and make it executable with:

chmod +x .git-templates/hooks/prepare-commit-msg
Enter fullscreen mode Exit fullscreen mode


Option 3: Advanced case: make the git hook work alongside other prepare-commit-msg hooks

Only one script can be executed in each specific git hook, so in order to run multiple scripts for one hook, we'll need to create a parent script that will invoke all others.

Change the content of you prepare-commit-msg for this:

Create a folder named prepare-commit-msg.d in the same folder and move all your other prepare-commit-msg hook scripts into it. Your hooks folder structure should look similar to:

.git-templates/hooks
├── prepare-commit-msg
└── prepare-commit-msg.d
    ├── add-co-authors
    ├── some-script
    ├── ...
    └── some-other-script
Enter fullscreen mode Exit fullscreen mode

Don't forget to make every script executable with:

chmod +x {path-to-my-script}
Enter fullscreen mode Exit fullscreen mode

If you this globally remember to make it available in the repo you want by entering the repo folder and running:

git init
Enter fullscreen mode Exit fullscreen mode

4. Create the template ✍️

In your repo folder run:

git mob --installTemplate && touch .git/.gitmessage
Enter fullscreen mode Exit fullscreen mode

This will create the file .git/.git-mob-template where it will write the selected co-authors into.

5. Start a mob/pairing session 👯‍♀️

When you start working with your teammates type:

git mob foo bar
Enter fullscreen mode Exit fullscreen mode

The names you use here are the same you used on the .git-coauthors file before.

When you do git commit you'll see this already in the message:

Co-authored-by: Foo <foo@company.com>
Co-authored-by: Bar <bar@company.com>
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
Enter fullscreen mode Exit fullscreen mode

6. Work alone 🤷

To start working by yourself just type:

git solo
Enter fullscreen mode Exit fullscreen mode

Other useful commands

  • Show current co-authors:
git mob --print
Enter fullscreen mode Exit fullscreen mode
  • Show all available co-authors and their aliases:
git mob --list
Enter fullscreen mode Exit fullscreen mode

Check https://github.com/findmypast-oss/git-mob for more info.

Oldest comments (0)