はじめに
パッケージロックファイル (例: package.json => package-lock.json) やOAS (OpenAPI Specification) の生成ソースコード (例: swagger.json => src/**.ts) などの生成系の巨大ファイルの変更がコンフリクトした場合、真面目にマージしようとしないでください。
代わりに自動生成しなおしてください。
毎年新人にこの手のアドバイスをしている気がするので記事として残しておきます。
具体例: package-lock.json のコンフリクト
たとえば、以下のようなケースを考えます。
- Aさんが
feature-aブランチでlodashを追加 - あなたが
feature-bブランチでaxiosを追加 - Aさんのブランチが先に
mainへマージされた - あなたのブランチをマージしようとすると……
$ git merge main
Auto-merging package-lock.json
CONFLICT (add/add): Merge conflict in package-lock.json
Auto-merging package.json
CONFLICT (content): Merge conflict in package.json
Automatic merge failed; fix conflicts and then commit the result.
package.json と package-lock.json がコンフリクトしているようです。
「解消しなきゃ……!」
package.json のコンフリクトはシンプルです。両方の依存を残せばOK。
"dependencies": {
<<<<<<< HEAD (自分: feature-b)
"axios": "^1.13.6"
=======
"lodash": "^4.17.23"
>>>>>>> main (Aさん側)
}
問題は package-lock.json です。こちらは300行超のコンフリクトになります。
"packages": {
"": {
"dependencies": {
<<<<<<< HEAD (自分: feature-b)
"axios": "^1.13.6"
}
},
"node_modules/asynckit": { ... },
"node_modules/axios": { ... },
"node_modules/combined-stream": { ... },
"node_modules/follow-redirects": { ... },
"node_modules/form-data": { ... },
... (axios の依存ツリーがさらに十数パッケージ続く)
=======
"lodash": "^4.17.23"
}
},
"node_modules/lodash": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
...
>>>>>>> main (Aさん側)
これを手作業で正しくマージするのは現実的ではありませんし、やるべきではありません。
正しい解消方法
package-lock.json のような生成物は、いったん相手側をそのまま受け入れてから再生成します。1
# 1. package.json は両方の依存を残す形で手動マージ(簡単)
# 2. package-lock.json は相手側(main)をそのまま受け入れる
# (自分が後でマージする予定なので、相手側を優先)
git checkout --theirs package-lock.json
# 3. マージ済みの package.json から再生成
npm install
# 4. コミット
git add package.json package-lock.json
git commit
(補足) 実は npm 自身でコンフリクトマーカーを解消できる
実は npm 5.7.0 以降では、package-lock.json にコンフリクトマーカーが残ったままでも npm install を実行すれば自動的に解消されます。2
As of
npm@5.7.0, these conflicts can be resolved by manually fixing anypackage.jsonconflicts, and then runningnpm install [--package-lock-only]again. npm will automatically resolve any conflicts for you and write a merged package lock that includes all the dependencies from both branches in a reasonable tree.
# 1. package.json のコンフリクトを解消(これは必要)
# 2. package-lock.json はコンフリクトマーカーが残ったまま npm install
npm install
# → npm がコンフリクトマーカーを見てマージ済みの lockfile を生成してくれる
同様の機能を pnpm (v5.11+) や yarn (v1.0+) も持っているようなので、使ってみてもいいかもしれません。(本記事の趣旨とは異なりますが)
まとめ 〜 他の自動生成系ファイルも同じ
この考え方は package-lock.json に限らず、冒頭で述べた OAS (OpenAPI Specification) なども同じです。とにかく一生懸命マージしないで(AIにさせようとせず)、以下を行いましょう。
- 自動生成されたファイルのコンフリクトを手動マージしようとしない
- 生成元ファイル(
package.jsonなど)のコンフリクトを正しく解消する - 生成コマンド(
npm installなど)を再実行して派生ファイルを作り直す
生成元のソースについて適切にマージできているのであれば、派生物は生成しなおしたものを使いましょう。3