├── .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 |
--------------------------------------------------------------------------------