Resolving Git conflicts with Javascript Challenge:
Resolve git conflict by resolveGitConflict(linesArray, resolveMode), where
linesArray is an array of strings
Example:
[
    &quot;context1&quot;, 
    &quot;context2&quot;, 
    &quot;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;, 
    &quot;my changes1&quot;, 
    &quot;=======&quot;, 
    &quot;their changes1&quot;,
    &quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&quot;,
    &quot;context3&quot;,
    &quot;context4&quot;,
    &quot;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;, 
    &quot;my changes2&quot;, 
    &quot;=======&quot;, 
    &quot;their changes2&quot;,
    &quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&quot;,
    &quot;context5&quot;,
    &quot;context6&quot;
]   

resolveMode -  a string indicate:

m: Keep only current branch's changes
t: Keep only other branch's changes
tm: Keep both changes, but put other branch's changes before current branch's changes
mt - Keep both changes, but put other branch's changes after current branch's changes
none - Keep no changes

Review
We have three solutions for that challenge. Please compare  all of them and tell which one is better.
Solution 1
const resolveGitConflict = (linesArray, resolveMode, t = []) =&gt;
  linesArray.reduce((p, c) =&gt; p.concat(
    t.length ?
      c === '&gt;&gt;&gt;&gt;&gt;&gt;&gt;' ?
        (c = [].concat(resolveMode[0] ? t.splice(+(resolveMode[0] === 't'), 1)[0].concat(resolveMode[1] ? t[0] : []) : [])) &amp;&amp;
        (t = []) &amp;&amp; c
      : c === '=======' ? t[1] = [] : t[+!!t[1]].push(c) &amp;&amp; []
    : c === '&lt;&lt;&lt;&lt;&lt;&lt;&lt;' ? t[0] = [] : [c]
  ), [])

Solution 2
function resolveGitConflict(linesArray, mode) {
    var [changes, curMode] = [{m: [], t: []}, ''];
    return linesArray.map(line =&gt; {
        var newLines = [];
        if (line === '&lt;&lt;&lt;&lt;&lt;&lt;&lt;' || line === '=======')
            curMode = line === '&lt;&lt;&lt;&lt;&lt;&lt;&lt;'? 'm' : 't';
        else if (line === '&gt;&gt;&gt;&gt;&gt;&gt;&gt;') { 
            newLines = Array.from(mode).map(c =&gt; changes[c] || []).flat(1);
            [changes.m, changes.t, curMode] = [[], [], ''];
        } else
            (changes[curMode] || newLines).push(line);
        return newLines;
    }).flat(1);
}

Solution 3
function resolveGitConflict(lines, mode) {
  return lines.reduce((p, c) =&gt; {
    let last = p[p.length-1]
    if(typeof last === 'object' ) {
      if(c === '&gt;&gt;&gt;&gt;&gt;&gt;&gt;') last = [].concat(last[mode[0]] || [], last[mode[1]] || [])
      else if(c === '=======') last.t = [] 
      else last[last.t ? 't' : 'm'].push(c)
      return p.slice(0, -1).concat(last)
    } else if(c === '&lt;&lt;&lt;&lt;&lt;&lt;&lt;') c = {m: []}        
    return p.concat(c)
  }, [])
}
It is difficult to tell &quot;which one is better&quot;. As Jan mentioned in a comment:

&quot;tell which one is better&quot; - what does &quot;better&quot; mean? performance? code readability? ... ?

The notion of better is subjective.
I am drawn to the first solution as it uses the fewest lines, though readability suffers because the lines are quite long and there are nested ternary operators.
I notice Solution 2 uses ES6 features like arrow functions (as all solutions do) yet it uses the var keyword. Some believe there is no use for var in modern JS. The variable newLines could be declared with const if instead of re-assigning it in the else if block the length property was set to 0 to truncate it and the mapped values were spread into a call to the push method. Using const instead of let helps avoid accidental re-assignment and other bugs.