git | test github renamer | source tree | Search

This code analyzes a Git repository and generates a structured representation of its commit history, essentially creating a visual "tree" of branches and commits that can be used for visualization or further processing.

Run example

npm run import -- "json git tree"

json git tree

var execSync = require('child_process').execSync;
/*var {
    execCmd
} = importer.import("spawn child process");*/


function gitTree(project) {
    console.log('creating tree "' + project + '"');
    var branches = execSync('git branch --list --all ', {cwd: project}).toString()
        .trim().split(/\s*\n\s*\**\s*/ig)
        .map(b => b.replace('remotes/', '').trim());

    // reverse git so we can add merges to the "graph" after the branch tree is constructed
    var branch = execSync('git log --pretty=format:"%ct %d %h %p" '
        + '--reverse --branches --tags ', {cwd: project}).toString().split(/\s*\n\s*/ig);
    var all = []; //execSync('git log --pretty=format:"%h %p" --reverse --all').toString().split(/\s*\n\s*/ig);

    var nodes = [];
    var edges = [];
    branch.forEach(b => {
        var commits = ((/[0-9]+\s+\(.*?\)\s*(.+)/ig).exec(b)
            || (/[0-9]+\s+(.+)/ig).exec(b) || [b, b.trim()])[1].trim().split(/\s+/ig);
        commits.forEach(r => {
            if (nodes.filter(d => d.name == r).length == 0) {
                nodes[nodes.length] = {
                    name: r,
                    index: nodes.length,
                    branch: ((/[0-9]+\s+\((.*?)\)/ig).exec(b) || [b, ''])[1],
                    time: (/([0-9]+)\s+/ig).exec(b)[1]
                }
            }
        });
        // don't include merges in tree
        if (commits.length == 3) {
            commits = [commits[0], commits[1]];
        }
        if (commits.length == 2) {
            edges = edges.concat(commits.slice(1)
                // check all existing sources to test for merge
                .map((c, i) => {
                    return {source: c, target: commits[i]}; // -1 because of slice(1)
                }))
        }
    });

    return formatNodes(nodes, edges.reverse());
}
module.exports = gitTree;

What the code could have been:

const childProcess = require('child_process');
const console = console;

/**
 * Creates a graph representation of a Git repository tree.
 * @param {string} project - The path to the Git repository.
 * @returns {object} - The graph nodes and edges.
 */
function gitTree(project) {
  console.log(`Creating tree for project: ${project}`);

  // Get a list of all branches and tags
  const branches = getBranches(project);

  // Get a list of commits in reverse chronological order
  const commits = getCommits(project);

  // Initialize nodes and edges arrays
  const nodes = [];
  const edges = [];

  // Process each commit
  commits.forEach((commit) => {
    const [date, merge, hash, parents] = commit.split(' ');
    const parentsArray = parents.trim().split(' ');

    // Create nodes for each parent
    parentsArray.forEach((parent, index) => {
      if (!nodes.find((node) => node.name === parent)) {
        nodes.push({
          name: parent,
          index: nodes.length,
          branch: getBranch(hash),
          time: date,
        });
      }
    });

    // Add edges between parents if not merge commits
    if (parentsArray.length > 1) {
      for (let i = 1; i < parentsArray.length; i++) {
        edges.push({ source: parentsArray[i - 1], target: parentsArray[i] });
      }
    }
  });

  return formatNodes(nodes, edges.reverse());
}

// Helper function to get a list of branches
function getBranches(project) {
  return childProcess
   .execSync(`git branch --list --all`, { cwd: project })
   .toString()
   .trim()
   .split(/\s*\n\s*\*\s*/ig)
   .map((b) => b.replace('remotes/', '').trim());
}

// Helper function to get a list of commits
function getCommits(project) {
  return childProcess
   .execSync(
      'git log --pretty=format:"%ct %d %h %p" --reverse --branches --tags',
      { cwd: project }
    )
   .toString()
   .split(/\s*\n\s*/ig);
}

// Helper function to get the branch name for a commit
function getBranch(hash) {
  const branch = childProcess
   .execSync(`git branch --list --contains ${hash}`, { cwd: process.cwd() })
   .toString()
   .trim()
   .split(/\s*\n\s*/ig)[0];
  return branch.replace('remotes/', '').trim();
}

// Helper function to format nodes and edges
function formatNodes(nodes, edges) {
  return { nodes, edges };
}

module.exports = gitTree;

This code defines a function gitTree that analyzes a Git repository and generates a structured representation of its commit history, essentially creating a visual "tree" of branches and commits.

Here's a breakdown:

  1. Initialization:

  2. Fetching Branch Information:

  3. Fetching Commit History:

  4. Building the Tree Structure:

  5. Formatting the Output:

  6. Returning the Tree:

Let me know if you have any other code snippets you'd like me to explain!