├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── git-author ├── git-author.bats └── setup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Xin Zhang 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: check 2 | check: 3 | bats -t git-author.bats 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

VMware has ended active development of this project, this repository will no longer be updated.


2 | 3 | # git-author 4 | A simple tool to add multiple authors to commit messages. Under the hood it is 5 | based on `git commit --template` and depends on `git-together`. 6 | 7 | # Setup 8 | 9 | ## Installation 10 | 11 | Because `git-author` is a shell wrapper around 12 | [`git-together`](https://github.com/kejadlen/git-together), both must be 13 | installed on the system. 14 | 15 | ### MacOS 16 | 17 | ``` 18 | brew install pivotal/tap/git-author 19 | ``` 20 | 21 | ### Linux 22 | 23 | The `git-together` and `git-author` executables must be installed somewhere on 24 | your path so that git recognizes commands that begin with `git together` or 25 | `git author`. 26 | 27 | #### Install and configure git-together 28 | 29 | You can follow the instructions here: https://github.com/kejadlen/git-together 30 | We suggest using `git config --global` for the following instructions, since 31 | it's better to share the same git-together settings across all repos. 32 | 33 | For your convenience, only the necessary settings are repeated here: 34 | 35 | ```sh 36 | # include git-together configuration in ~/.gitconfig 37 | git config --global --add include.path ~/.git-together 38 | 39 | # Add the below line to your .bashrc to disable the 40 | # `--signoff`s added by `git-together commit`. 41 | export GIT_TOGETHER_NO_SIGNOFF=1 42 | ``` 43 | 44 | Note: Because `git-author` calls `git-together` directly to generate a 45 | commit template file, aliasing `git` to `git-together` is not strictly 46 | necessary, unless you want git author info to alternate among members of the 47 | pair or mob as you make commits. With `Co-authored-by: ` in the commit 48 | message, Github will show all authors regardless of the git author info. 49 | 50 | #### Install git-author 51 | 52 | ``` 53 | git clone git@github.com:pivotal/git-author 54 | ./git-author/setup.sh 55 | ``` 56 | 57 | # Usage 58 | Set the authors as below: 59 | 60 | ``` 61 | # pairing with James and Naomi 62 | git author jh nn 63 | 64 | # soloing 65 | git author jh 66 | 67 | # mobbing 68 | git author jh nn ca 69 | 70 | # show who are included in current ~/.git-author-template 71 | git author 72 | ``` 73 | 74 | After doing so, `git commit` will now automatically include all of the authors 75 | in the commit message with the prefix `Co-authored-by:` or `Authored-by` if 76 | there is only one author. For example: 77 | 78 | ``` 79 | # mobbing 80 | git author jh nn ca 81 | 82 | # commit 83 | git commit 84 | 85 | # the commit message is pre-populated as: 86 | 87 | 88 | Co-authored-by: James Holden 89 | Co-authored-by: Naomi Nagata 90 | Co-authored-by: Chrisjen Avasarala 91 | 92 | 93 | # soloing 94 | git author ca 95 | 96 | # commit 97 | git commit 98 | 99 | # the commit message is pre-populated as: 100 | 101 | 102 | Authored-by: Chrisjen Avasarala 103 | ``` 104 | 105 | ## Story Numbers 106 | Often when making commits, we like to append the commit message with a story 107 | number, e.g. `[#12345678]`. To automate this process, you can set the 108 | `$STORY_NUM` environment variable to a value such as `'#12345678 story title'`. 109 | Run `git author` again for the story number to appear in the commit message. 110 | This will result in the below being appended to the commit message template: 111 | 112 | ``` 113 | [#12345678] 114 | # story title 115 | 116 | Co-authored-by: ... 117 | Co-authored-by: ... 118 | ``` 119 | 120 | Additionally, if you set `git config --global git-author.includeBlankStoryNum true`, 121 | then if you didn't set `$STORY_NUM`, empty story number brackets ('[]') will be 122 | appended to prompt you to fill it in. 123 | 124 | ## Global vs. Local `git-together` Settings 125 | By default, `git-together` will be called with `--global`, hence a system-wide 126 | configuration of authors are set. 127 | 128 | However, for special cases, people like to use non-global configurations just for 129 | given set of git repos. To support that usage, we introduced another environment 130 | variable `GIT_AUTHOR_LOCAL`. 131 | 132 | If this variable it set `git-together` will be called without `--global` flag. 133 | Here is the example usage for non-global usage: 134 | 135 | ``` 136 | GIT_AUTHOR_LOCAL=1 git author jh 137 | ``` 138 | 139 | If people always wants to use it without `--global`, then can put this environment in 140 | their shell environment, e.g. `.bashrc`. 141 | 142 | # Why 143 | `git-together` is a wonderful tool to change the `author` and `commit` fields 144 | in the git commit object, and rotate the authors automatically to evenly 145 | distribute the credit. 146 | 147 | However, both the git `author` and `commit` fields may change or be lost in the 148 | future due to merging, rebasing, and cherry-picking. 149 | 150 | Also, `git-together` cannot put multiple authors directly into same commit, 151 | e.g. it only supports one `Signed-off-by:` message generated by `git commit 152 | --signoff`. 153 | 154 | `git-author` is created to extend the `git-together` capability, so that all 155 | the authorship information will be captured as part of the commit message, 156 | hence, it won't care about who actually tracked in the `author` and `commit` 157 | fields in the git log. 158 | 159 | See this discussion on the open source GPDB project's mailing list: 160 | https://groups.google.com/a/greenplum.org/forum/#!msg/gpdb-dev/qHqa9UbFpSA/u0Y0g2rqAAAJ 161 | 162 | # Development 163 | `git-author` is a bash script, we used [bats](https://github.com/bats-core/bats-core) 164 | to verify the functionality of this script. 165 | 166 | ```bash 167 | # run the tests 168 | make 169 | ``` 170 | 171 | You are welcome to extend this utility. Please make sure adding new tests to cover your 172 | scenario first. 173 | -------------------------------------------------------------------------------- /git-author: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | setup_env() { 4 | git_author_file_name=${HOME}/.git-author-template 5 | # Make sure the template file exists 6 | touch "${git_author_file_name}" 7 | } 8 | 9 | print_story_num() { 10 | if [ "$(git config git-author.includeBlankStoryNum)" = 'true' \ 11 | -o -n "${STORY_NUM}" ]; then 12 | <<<"${STORY_NUM}" read story_num story_comment 13 | echo "[${story_num}]" 14 | echo "# ${story_comment}" 15 | echo "" 16 | fi 17 | } 18 | 19 | insert_author_tags() { 20 | local number_of_authors="${1}" 21 | if [ "$number_of_authors" -eq 1 ]; then 22 | sed "s/.*/Authored-by: &/" 23 | else 24 | sed "s/.*/Co-authored-by: &/" 25 | fi 26 | } 27 | 28 | git-together-dependency() { 29 | git-together $@ 30 | } 31 | 32 | git-author-main() { 33 | local first_author="${1}" 34 | 35 | setup_env 36 | 37 | if [ -z "${GIT_AUTHOR_LOCAL}" ]; then 38 | GIT_TOGETHER_OPTION='--global' 39 | fi 40 | 41 | if [ -n "${first_author}" ]; then 42 | ( 43 | echo "" 44 | echo "" 45 | print_story_num 46 | # always clean-up the git-together.active settings 47 | git-together-dependency with --clear 2>/dev/null || true 48 | git-together-dependency with ${GIT_TOGETHER_OPTION} "$@" | insert_author_tags $# 49 | ) > "${git_author_file_name}" 50 | fi 51 | 52 | # echo the script, but do not print blank lines because it's clutter on the terminal 53 | <"${git_author_file_name}" awk '!/^$/{print}' 54 | } 55 | 56 | if [ "${BASH_SOURCE}" = "${0}" ]; then 57 | git-author-main $@ 58 | fi 59 | -------------------------------------------------------------------------------- /git-author.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | source "${BATS_TEST_DIRNAME}/git-author" 4 | 5 | # helper functions 6 | git-together-dependency() { 7 | echo "$@" >> /tmp/git-together-dependency-args 8 | } 9 | 10 | log() { 11 | echo "$@" >&3 12 | } 13 | 14 | # tests 15 | setup() { 16 | rm -f /tmp/git-together-dependency-args 17 | } 18 | 19 | @test "using --global by default" { 20 | run git-author-main ab 21 | [ "${status}" -eq 0 ] 22 | 23 | run cat /tmp/git-together-dependency-args 24 | [ "${lines[0]}" = 'with --clear' ] 25 | [ "${lines[1]}" = 'with --global ab' ] 26 | } 27 | 28 | @test "not using --global if GIT_AUTHOR_LOCAL is defined" { 29 | GIT_AUTHOR_LOCAL=1 run git-author-main ab 30 | [ "${status}" -eq 0 ] 31 | 32 | run cat /tmp/git-together-dependency-args 33 | [ "${lines[0]}" = 'with --clear' ] 34 | [ "${lines[1]}" = 'with ab' ] 35 | } 36 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 3 | 4 | GIT_AUTHOR_FILE_NAME=${HOME}/.git-author-template 5 | 6 | # create an empty template if it doesn't exist 7 | touch ${GIT_AUTHOR_FILE_NAME} 8 | 9 | # config git to use a commit template 10 | git config --global commit.template ${GIT_AUTHOR_FILE_NAME} 11 | 12 | # put git-author to search path, so that `git author` works. 13 | cp ${SCRIPT_DIR}/git-author /usr/local/bin 14 | --------------------------------------------------------------------------------