frinyvonnick / gitmoji-changelog

A changelog generator for gitmoji 😜
https://www.npmjs.com/package/gitmoji-changelog
MIT License
390 stars 49 forks source link

Sort / Group similar commits #44

Closed fabienjuif closed 6 years ago

fabienjuif commented 6 years ago

We can group together commit that are similars, like:

Should be grouped together so we can merge them manually after gitmoji-changelog is ran.

fabienjuif commented 6 years ago

POC

const levenshtein = require('fast-levenshtein')

const first = 'update README.md'
const second = 'Update README'
const third = 'README updated'
const fourth = 'Release v1.2.0'
const fifth = 'v1.2.0 released!'
const alone = 'I should be alone'

const all = [fifth, second, alone, fourth, first, third]

// group closed meanings messages together (using indexes)
const getGroupedMessagesByMeaning = (messages) => {
  const sortedWords = messages.map(message => message.split(' ').sort().join(''))
  const closedMeaningMessages = new Map()
  for (let i = 0; i < sortedWords.length; i += 1) {
    for (let j = i + 1; j < sortedWords.length; j += 1) {
      const distance = levenshtein.get(sortedWords[i], sortedWords[j])
      if (distance < 10) {
        closedMeaningMessages.set(i, new Set([...(closedMeaningMessages.get(i) || []), j, i]))
        closedMeaningMessages.set(j, new Set([...(closedMeaningMessages.get(j) || []), i, j]))
      }
    }
  }

  return closedMeaningMessages
}

// construct results
const groupedMessagesByMeaning = getGroupedMessagesByMeaning(all)
const results = new Set()
all.forEach((message, index) => {
  if (!groupedMessagesByMeaning.get(index)) {
    results.add(message)
    return
  }

  const closedMeaning = Array.from(groupedMessagesByMeaning.get(index))
  for (let i = 0; i < closedMeaning.length; i += 1) {
    results.add(all[closedMeaning[i]])
    groupedMessagesByMeaning.delete(closedMeaning[i])
  }
})

// logs
console.log('before', all)
console.log('groups', getGroupedMessagesByMeaning(all))
console.log('after', results)
➜  gitmoji-changelog-levenshtein git:(master) ✗ node test.js
before [ 'v1.2.0 released!',
  'Update README',
  'I should be alone',
  'Release v1.2.0',
  'update README.md',
  'README updated' ]
groups Map {
  0 => Set { 3, 0 },
  3 => Set { 0, 3 },
  1 => Set { 4, 1, 5 },
  4 => Set { 1, 4, 5 },
  5 => Set { 1, 5, 4 } }
after Set {
  'Release v1.2.0',
  'v1.2.0 released!',
  'update README.md',
  'Update README',
  'README updated',
  'I should be alone' }
➜  gitmoji-changelog-levenshtein git:(master) ✗
fabienjuif commented 6 years ago

Right now the changes object given by core is structured as this:

[
  version: '',
  groups: [
    {
       group: '',
       label: '',
       commits: [
         {
           hash: '',
           // ...
         },
       ],
    }
  ],
]

What I propose is this:

[
  version: '',
  groups: [
    {
       group: '',
       label: '',
       commits: [
         {
           hash: '',
           // ...
           siblings: [/* commits */]
         },
       ],
    }
  ],
]

commits that are in siblings are NOT listed into changes[].groups[].commits.

The resulting markdown could be:

v1.0.0

Added