yarn.lock 文件的冲突解决

2021-04-22 · 5 min read

起因

在某次需求开发中新增了一个npm包,在进行代码合并时,yarn.lock 产生了合并冲突。

这种情况下,我通常都是直接 yarn install 解决。

不过一直都没关注 yarn install 到底怎么解决的冲突,这次就来简单梳理下 yarn.lock 冲突解决背后发生了什么。

解决 yarn.lock 冲突的方法

经过一番搜寻,发现目前有三种方式来搞。

一是手动解决,纯手工一个一个对比冲突。 这种方式如果只有几个小的改动还行,当你的 yarn.lock 改动很多,那么手动是没法搞定的。

二是先将 yarn.lock 还原为 base branch 的版本(通常是 origin/master ),解决完 package.json 的冲突后,再进行 yarn install

git checkout origin/master -- yarn.lock
yarn install

三是直接进行 yarn install,把冲突解决交给 yarn 来处理。

yarn install
  ...
  yarn install v1.22.4
  info Merge conflict detected in yarn.lock and successfully merged.
  ...

那么 yarn install 的冲突解决策略是怎样的呢?我又搜寻了一番,但并没有发现有相关的文章描述这个策略。

不过我通过Yarn 1.0的发布日志找到了这个feature的merge request,并在这个mr下找到了对应的测试用例,我们可以通过这些测试用例来大概了解下 yarn install 的冲突解决策略。

(既然找到了对应的文件,我选择直接看最新版本的测试用例就好了) https://github.com/yarnpkg/yarn/blob/master/__tests__/lockfile.js

测试用例中 yarn install 的冲突解决策略有这几种情况:

  • 单个简单冲突
const file = `
a:
  no "yes"
<<<<<<< HEAD
b:
  foo "bar"
=======
c:
  bar "foo"
>>>>>>> branch-a
d:
  yes "no"
`
{
    a: {no: 'yes'},
    b: {foo: 'bar'},
    c: {bar: 'foo'},
    d: {yes: 'no'},
}
  • 带CRLF的单个简单冲突
const file =
    'a:\r\n  no "yes"\r\n\r\n<<<<<<< HEAD\r\nb:\r\n  foo "bar"' +
    '\r\n=======\r\nc:\r\n  bar "foo"\r\n>>>>>>> branch-a' +
    '\r\n\r\nd:\r\n  yes "no"\r\n';
{
    a: {no: 'yes'},
    b: {foo: 'bar'},
    c: {bar: 'foo'},
    d: {yes: 'no'},
}
  • 多个冲突
const file = `
a:
  no "yes"
<<<<<<< HEAD
b:
  foo "bar"
=======
c:
  bar "foo"
>>>>>>> branch-a
d:
  yes "no"
<<<<<<< HEAD
e:
  foo "bar"
=======
f:
  bar "foo"
>>>>>>> branch-b
`
{
    a: {no: 'yes'},
    b: {foo: 'bar'},
    c: {bar: 'foo'},
    d: {yes: 'no'},
    e: {foo: 'bar'},
    f: {bar: 'foo'},
}
  • 冲突合并失败
const file = `
<<<<<<< HEAD
b:
  foo: "bar
=======
c:
  bar "foo"
>>>>>>> branch-a
`
0
  • 丢弃冲突的公共祖先
const file = `
<<<<<<< HEAD
b:
  foo "bar"
||||||| common ancestor
d:
  yes "no"
=======
c:
  bar "foo"
>>>>>>> branch-a
`
{
    b: {foo: 'bar'},
    c: {bar: 'foo'},
}

简单浏览完之后,发现大致的策略就是冲突时尽量保留两者,感兴趣的同学还可以直接看看源码中是怎么处理 lockfile 的,位置在 /src/lockfile/parse.js

在我看来,手动解决适合一两个冲突的解决。

而直接使用 yarn install 和 还原 yarn.lockbase branch 后再进行 yarn install 都是可行的方法。

当然,还有上面没提及的:直接删除 yarn.lock,再 yarn install,这种方式风险巨大,强烈不推荐。

小结

解决 yarn.lock 冲突背后还涉及很多知识点,比如

  • yarn.lockpackage-lock.json 的机制?
  • 安装缓存 yarn cache npm cache
  • yarn install 的过程,模块扁平化

… …

平时还是应该多多深入了解使用的工具,来避免一些令人惊喜的BUG的产生。

参考


Profile picture

Blogs by Leo Yang who lives and works in Chengdu writing interesting things. You should follow me on Github 😁