Description
This is not a critical bug but is little boring have to remove this extra rule always that I added a new rule to vercel.
Details
- CLI Version: 37.12.1
- OS: Microsoft Windows 11 Pro
Evidence

Steps to reproduce the issue
- Using an OS that has end-of-line
crlfby default like Windows - Run
vercel env pullInto a project that already has a the vercel rules into the.gitignore
What’s the expected result?
Only add the rule .env*.local when the .gitignore does not have it.
What’s the actual result?
Is adding the same rule multiple times.
Root cause
This is happeing because this condition in this file packages/cli/src/util/link/add-to-gitignore.ts this is the code:
const EOL = gitIgnore.includes('\r\n') ? '\r\n' : os.EOL;
// ..
if (!gitIgnore.split(EOL).includes(ignore)) { /* add the rule */
In some cases this condition can be translated to:
const EOL = gitIgnore.includes('\r\n') ? '\r\n' : '\r\n';
For example in my case my file is using lf = \n but my os use crlf = \r\n by default that is this condition will never be true.
Solution
I did a few changes in this code that I would like to check first here to avoid a forgotten PR!
Changes
-
Move this file
add-to-gitignore.tsfromsrc/util/linktosrc/utilsince it is not only used in link command but also in env command. -
Change the code to check as an string. It is good for two reasons:
- The
.gitignorecan have multiples rules at the same line - Doesn’t matter what is the end-of-line
- The
if (gitIgnore.includes(ignore)) return isGitIgnoreUpdated;
- The last change that I would like to check if it is ok
or is too much. I created a function to get the dominant end-of-line and use it when add a new line. This is the code:
function getDominantEOL(text: string) {
const lines = (text.match(/\r\n|\n/g) ?? []) as Array<'\r\n' | '\n'>;
const {
'\n': LFCount,
'\r\n': CRLFCount,
} = lines.reduce(
(counter, lineEnding) => {
counter[lineEnding] += 1;
return counter;
},
{ '\n': 0, '\r\n': 0 },
);
const dominantEOL = LFCount > CRLFCount ? '\n' : '\r\n';
return LFCount === CRLFCount ? os.EOL : dominantEOL;
}
It can be simpler checking if there is any kind of end-of-line otherwise it uses the os end-of-line:
function getEOL(text: string) {
if (text.includes('\r\n')) return '\r\n';
if (text.includes('\n')) return '\n';
return os.EOL;
}
I will open the PR soon and leave the link to it here!
If you have any suggestions I will be happy to apply it ![]()