📌

【お詫び】サバイバルTypeScriptにおける、コントリビューションの横取りについて

2023/02/23に公開3

この度、わたくしsuinが、サバイバルTypeScriptプロジェクトにおいて、コントリビューター様の貢献の横取りともとられかねない失態を犯し、大変なご迷惑をおかけしたことを深くお詫び申し上げます。このお詫びは、私の失態に対して、誠意を持って向き合い、改善に努めるとともに、本件に関わる全ての方々にお詫びを申し上げるものです。

背景

サバイバルTypeScriptは、TypeScriptの入門書であり、ウェブサイトとして公開されており、無料で閲覧できます。このサイトは、月間7万人以上のユニークユーザーが訪れ、多くの方々にご利用いただく書籍となっています。

https://typescriptbook.jp/

さらに、サバイバルTypeScriptはオープンソースプロジェクトであり、2019年にわたくしsuinの発案で発足し、現在は3年目になります。プロジェクトはGitHub上で管理され、これまで50名を超えるコントリビューターにご参加いただきました。多くのコントリビューターの皆様によって支えられているオープンソースプロジェクトとなっております。

https://github.com/yytypescript/book

また、サバイバルTypeScriptの開発には、毎週1回「執筆回」というオンラインイベントが開催され、Discord上でコントリビューターが集って活動しています。このほかにも、本書の誤りの指摘や内容に関する質問などはGitHub Issuesで受け付けており、GitHubのプルリクエストも随時受け付けています。皆様のご意見やご要望を反映しつつ、よりよいサバイバルTypeScriptを目指す体制を取っております。

このように多くの方々に支えられているサバイバルTypeScriptに対し、今回のわたくしの失態により、多大なご迷惑をおかけしてしまいましたことを深くお詫び申し上げます。

本件の概要

まず、コントリビューター様より、内容の誤りを訂正するプルリクエストを頂戴しました。しかしながら、私がそのプルリクエストをissueと誤認してしまい、私名義のプルリクエストを別途作成し、それをマージしてしまいました。この結果、コントリビューター様のご苦労や貢献が不適切な形で扱われ、ご不快な思いをおかけし、功績の横取りとも誤解されかねない結果となってしまいました。

その後、事後対応として、コントリビューター様に謝罪し、メインブランチのコミットログを調整して、コントリビューター様の功績が適切に残るように対応させていただきました。その上で、コントリビューター様からもお赦しを頂けている状況です。

本件の詳細については、以下にて順を追ってご説明させていただきます。このような失態が起こらないよう、今後もより慎重な対応に努めてまいります。

経緯

本件の全容をご理解頂くために、具体的な情報ソースをご提示しつつ、時系列順でご説明いたします。

2月18日 プルリクエストを受け取る

コントリビューター様から、本書の誤りを訂正するプルリクエストを頂きました。以下がそのプルリクエストのリンクです。

https://github.com/yytypescript/book/pull/585

このプルリクエストは、本書の誤りを正し、読者に正確な情報を伝える価値のある変更です。本書にコントリビュートするにあたっては、環境を構築して頂くだけでも時間の要する作業となり、また、目を通すドキュメントの量も決して少なくありません。成果物の背後にある努力は大きいものとなります。加えて、これまで蓄積した知識と経験、ならびに、才能も必要となる取り組みです。

通常であれば、このような価値が高く、労力・経験・知識・才能を要するプルリクエストは、謝意を表しつつ問題なくマージされるべきものです。

2月19日 私がプルリクエストを作成する

頂いたプルリクエストをきっかけに、私が修正に着手します。本来であれば、私が修正に着するのではなく、頂いたプルリクエストをマージするところです。しかし、今回は頂いたプルリクエストをissueと誤認したことから、失態が始まりました。

私は本書の問題箇所を修正し、修正内容を頂いたプルリクエストとは別のプルリクエストとして作成しました。

https://github.com/yytypescript/book/pull/588

私のプルリクエストの著者(author)は、私のみとなっておりました。この段階であっても、もし、頂いたプルリクエストが正しく認識できていた場合、コミットのauthorやco-authored-byを調整して、コントリビューター様の功績を適切に残すことができたはずですが、私はそのことに気づくことができませんでした。

2月22日6時 頂いたプルリクエストがCloseされる

頂いたプルリクエストを誤ってissueと認識し、私のプルリクエストの本文に「Close #585」と記載してしまいました。この記述は、GitHubではissueを閉じる命令として認識されます。この命令が記載されたプルリクエストがマージされると、指定されたissueが自動的にCloseされてしまいます。

私はこのようなプルリクエストをマージしてしまい、結果的に頂いたプルリクエストがCloseされてしまいました。同時に、私のプルリクエストはマージされたため、コントリビューター様の貢献がメインブランチに一切残らないコミットログが作成されてしまいました。このような状況により、私がコントリビューター様の貢献を横取りしたという誤解を招くことになってしまいました。

頂いたプルリクエストが自動でCloseされたため、なぜCloseされたかがコントリビューター様からは分からない状態になってしまい、コントリビューター様を不快な思いをさせてしまうことにも繋がりました。その際のコントリビューター様のお気持ちを察するには余りあるところがあり、深く反省しております。

2月22日15時 コントリビューター様からのご指摘

頂いたプルリクエストがCloseされたことを受けて、コントリビューター様からTwitterでご指摘を賜りました。

https://twitter.com/public_ai000ya/status/1628283034410823681

当時、コントリビューター様には上記の経緯が伝わっておらず、私がコントリビューター様の貢献を横取りしたとの誤解を招いてしまいました。コントリビューター様のご不快な思いをさせてしまい、深くお詫び申し上げます。コントリビューター様にとって、経緯が不明である以上、こうした内容でご指摘いただくことは至極当然なことであり、頂いたツイートは真摯に受け止めております。

2月22日20時 私がご指摘を確認する

私がTwitter上でコントリビューター様のツイートを発見します。そこではじめて、私が重大な過ちをしていることに気が付きました。

コントリビューター様のツイートをきっかけに、私の失態に気づくことになったわけですが、この点についても反省があり、コントリビューター様から指摘される前に、自分自身で気がついてすぐさま事態の修正に務めるべきだったと痛感しております。

また、コントリビューター様のツイートに直ちに気づくことができなかった点についても深く反省しております。

2月22日20時 コントリビューター様の貢献を取り込む

この件に対処するために、まずはコントリビューター様の貢献をメインブランチに統合する作業を開始しました。

まず、メインブランチには私のコミットが含まれていたため、これを取り除きました。GitHubリポジトリではメインブランチが保護されているため、一時的に保護を解除しました。その上で、私のコミットを取り除いたメインブランチをgit push -fでGitHubリポジトリに送信し、GitHub上でも私のコミットを削除しました。

頂いたプルリクエストのブランチが削除されたため、プルリクエストを再度オープンできなくなってしまっていました。そこで、頂いたブランチを復元し、コントリビューター様名義のコミットを取り出して、それを含む新しいプルリクエストを作成しました。

https://github.com/yytypescript/book/pull/591/commits

これをmasterにマージすることで、コントリビューター様の貢献がメインブランチに残ることになりました。以下は、メインブランチに取り込まれたコントリビューター様のコミットです。

https://github.com/yytypescript/book/commit/abbf6a4b3d4c759a60903a563dd2d876eabb9ea1

残念ながら、頂いたプルリクエストが再度オープンできなかったため、"Merged"の状態にすることができませんでした。このことは非常に残念です。私の技術力不足・知識不足でこの問題を解決することができなかったため、もしこの問題を解決する方法があれば教えていただけると幸いです。

なお、この対応で削除したコミットは私のコミットだけであり、これまでコントリビュートされた方々のコミットには影響がございませんので、ご安心いただけますと幸いです。

2月22日21時 コントリビューター様にお詫び

対応と謝罪が前後してしまい、この点においても反省がございますが、上の対応をした上でTwitterにてコントリビューター様にお詫びを申し上げました。

https://twitter.com/suin/status/1628366492235603969?conversation=none

https://twitter.com/suin/status/1628366555758358528?conversation=none

https://twitter.com/suin/status/1628366622749757440?conversation=none

https://twitter.com/suin/status/1628370498571894784?conversation=none

また、GitHubに頂いたプルリクエストのコメント欄にも同様のお詫びを記載致しました。

https://github.com/yytypescript/book/pull/585#issuecomment-1439918943

2月22日21時 コントリビューター様からのご返信

私のお詫びに対して、コントリビューター様からご返信を頂きました。私としては重大な失態を犯してしまっていたため、更にお叱りを受けることを覚悟しておりましたが、コントリビューター様からは大変前向きな寛大なご返信をいただきました。このようなご返信をいただけたことに深く感謝しております。

https://twitter.com/public_ai000ya/status/1628372414701903872?conversation=none

2月22日20時 ご不快な思いをさせた方々へお詫び

本件は、コントリビューター様がTwitterでご発信になってから、私の対応がひどく遅くなったため、コントリビューター様のツイートが広く拡散され、多くの方々のお耳に入ることとなってしまいました。

本件を知った方の中には、ご不快な思いをされた方も多くいらっしゃいました。本件によりご不快な思いをされた方々に向けて、Twitterでお詫びとご説明の文書を投稿致しました。

https://twitter.com/suin/status/1628383346974920704

この場を借りまして、本件によりご不快な思いをされたすべての皆様にも重ねてお詫び申し上げます。

本件について、Twitter上でご不快な思いを表明された方々については、ツイートを拝見させていただいているものもございまして、私のほうで把握できた方々については直接お詫びを申し上げるべきかとも考えましたが、それはそれで返ってご迷惑にもなりかねないと思い、まずは皆様に向けたツイートという形でお詫びさせていただきました。

以上が本件の経緯となります。

原因

ここからは、なぜこのような失態が起きたのか、その原因ついてご説明させていただきます。

本件はGitHubのissueとプルリクエストを見間違えたことに起因します。GitHubのissueとプルリクエストは似たUIであるものの、通常は見間違えるほどのものではないと考えております。

しかしながら、今回の見間違えが起こった原因として考えられることは、急ぐあまり注意散漫になっていたことが考えられます。

サバイバルTypeScriptは、技術書として多くの方に誤りのない情報を提供する責務があると考えております。そのため、明らかな誤りはできる限り迅速に修正される必要があります。

今回頂いたプルリクエストは、明らかな誤りを指摘・修正するものであり、迅速に対応されるべき内容でした。急ぐ気持ちが先行しすぎたため、頂いたプルリクエストを丁寧に見た上で対応することを怠ってしまいました。

対策

本件のような過ちが再発しないように、対策を講じて参ります。具体的には次の取り組みを実施する予定です。

  • ひとつひとつ慎重に対応する
  • GitHub Issueとプルリクエストの誤認を防ぐChrome拡張を入れる

まず、急ぎすぎず時間をかけて慎重に作業を進めることを心がけることにします。サバイバルTypeScriptは、多くの方に誤りのない情報を提供することを使命としているため、その使命を果たすためにも、細心の注意を払って作業を進める所存です。

次に、GitHub Issueとプルリクエストの誤認を防ぐため、Google Chrome拡張機能でユーザーCSSをGitHubに適用できるものを導入します。こうした拡張機能を使うと、GitHub上でIssueとプルリクエストの見た目をがらりと変更できるため、見間違いを防止しやすくなると考えております。

以上の対策を講じることで、今後同様のミスを起こさないように、万全を期したいと思います。

これまでに同様の失態がないかの調査

本件と同様の失態がないかを確認すべく、マージされずにクローズされたプルリクエストをすべて確認しました。結果としては、同様の失態は確認されませんでした。

調査したプルリクエストの内訳は次のとおりです。

  • お断りしたもの: 17
  • 作者によるClose: 8
  • 別PRで取り込んだもの: 5
  • 総数(全PR中マージされずCloseされたもの): 30

このうち、別PRで取り込んだものは、プルリクエスト作者様のお名前がmasterに残る形で取り込んだものになります。

おわりに

改めて、ご迷惑をおかけしたPR作者様、そして、本件により不快な思いをされたすべての皆様、また、サバイバルTypeScriptの読者の皆様、サバイバルTypeScriptを応援してくださっている方々やご心配をおかけした皆様、そしてこれまでにサバイバルTypeScriptにコントリビュートしてくださった全ての方々に、心よりお詫び申し上げます。

オープンソースプロジェクトにおいては、他者の貢献を横取りする行為は、本プロジェクトの信頼を損ねるだけでなく、オープンソース全体の信頼性も損ね、オープンソースの発展にも悪影響を与えることを深く認識し、本件を教訓として、コントリビューターの皆様が安心して貢献できる環境を守っていきたいと深く反省しております。

このような失態を二度と起こさないよう、今回の件を教訓として改善に努め、コントリビューターの皆様に信頼されるオープンソースプロジェクトとなるよう邁進してまいります。

Discussion

あいや - aiya000あいや - aiya000

こんにちは!
今回コントリビュートした者です🙋‍♂️
多くの防止策や、礼儀を感じられて、こちらとしてもうれしい限りです。

あとはやっぱり、issueでもPRでも、丁寧な返信コメントがあると、今回のたぐいのミスが起きても
「この人は礼儀を知っている。多分間違えたんだろう。」となるのかなと思いました(理想論ですが!)

今回は誠意ある対応を、ありがとうございました☺️

suinsuin

この度は、ご迷惑をおかけして大変失礼致しました。

ご提案いただいた「丁寧な返信コメント」はごもっともだと思いましたので、心がけるよう努めて参ります。
squashについての情報共有もありがとうございます。

他にも何かございましたら、遠慮なくお知らせいただければと思います。