DEV Community

Alba Rincón
Alba Rincón

Posted on

4 2

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:

#!/bin/sh
# This script should be saved in a git repo as a hook file, e.g. .git/hooks/pre-receive.
# It looks for scripts in the .git/hooks/pre-receive.d directory and executes them in order,
# passing along stdin. If any script exits with a non-zero status, this script exits.
script_dir=$(dirname $0)
hook_name=$(basename $0)
hook_dir="$script_dir/$hook_name.d"
if [[ -d $hook_dir ]]; then
stdin=$(cat /dev/stdin)
for hook in $hook_dir/*; do
echo "Running $hook_name/$hook hook"
echo "$stdin" | $hook "$@"
exit_code=$?
if [ $exit_code != 0 ]; then
exit $exit_code
fi
done
fi
exit 0

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.

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay