From 182bc4166112bb466a0b21fa16109e9b429afee7 Mon Sep 17 00:00:00 2001 From: Jelani Woods Date: Thu, 18 Jun 2020 13:53:16 -0500 Subject: [PATCH 1/5] Draw graph with gitgraph.js --- lib/views/status.erb | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lib/views/status.erb b/lib/views/status.erb index ad28da4..ef88dbb 100644 --- a/lib/views/status.erb +++ b/lib/views/status.erb @@ -261,6 +261,35 @@ <% end%> + + + <% @graph_branches.each do |branch_hash| %>

<%= branch_hash[:branch] %>

From 965771e4650a873801def375f07886a17dd3f6e1 Mon Sep 17 00:00:00 2001 From: Jelani Woods Date: Thu, 18 Jun 2020 23:05:15 -0500 Subject: [PATCH 2/5] WIP --- lib/views/status.erb | 18 +++++++++++++----- lib/web_git.rb | 4 ++-- lib/web_git/graph.rb | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/lib/views/status.erb b/lib/views/status.erb index ef88dbb..6fb22d1 100644 --- a/lib/views/status.erb +++ b/lib/views/status.erb @@ -270,12 +270,20 @@ author: "John Doe", mode: "extended" // or compact if you don't want the messages }); - <% bees = @graph_branches.first(4) %> - <% bees.each do |branch| %> - let <%= branch[:branch].gsub("-", "_") %> = gitgraph.branch("<%= branch[:branch] %>"); - <% branch[:log].reverse.each do |commit| %> - <%= branch[:branch].gsub("-", "_") %>.commit({message: '<%= commit[:message].to_s.gsub("\n", " ") %>', author: "<%= commit[:author] %>", sha1: "<%= commit[:sha] %>"}); + <% commits = @graph.to_array %> + <% commits.each_with_index do |commit, index| %> + //first <%= index %> + <% if index > 0 %> + //<%= index %> + <% previous_branches = commits.first(index)%> + <% if !previous_branches.map{|c| c[:branch_name]}.include?(commit[:branch_name]) %> + let branch_<%= commit[:branch_name].gsub("-", "_") %> = gitgraph.branch("<%= commit[:branch_name] %>"); + <% end %> + <% else%> + let branch_<%= commit[:branch_name].gsub("-", "_") %> = gitgraph.branch("<%= commit[:branch_name] %>"); <% end %> + branch_<%= commit[:branch_name].gsub("-", "_") %>.commit({message: '<%= commit[:message].to_s.gsub("\n", " ") %>', author: "<%= commit[:author] %>", sha1: "<%= commit[:sha] %>"}); + <% end %> // gitgraph.commit("My first commit"); // 1 commit upon HEAD // var develop = gitgraph.branch("develop"); // New branch from HEAD diff --git a/lib/web_git.rb b/lib/web_git.rb index 94e7625..2da569f 100644 --- a/lib/web_git.rb +++ b/lib/web_git.rb @@ -67,8 +67,8 @@ class Server < Sinatra::Base # (origin/master, origin/jw-non-sweet, origin/HEAD) # g.branches[:master].gcommit - graph = WebGit::Graph.new(g) - @graph_hash = graph.to_hash + @graph = WebGit::Graph.new(g) + @graph_hash = @graph.to_hash @graph_branches = @graph_hash.sort do |branch_a, branch_b| branch_b[:log].last[:date] <=> branch_a[:log].last[:date] end diff --git a/lib/web_git/graph.rb b/lib/web_git/graph.rb index bce555f..9156f62 100644 --- a/lib/web_git/graph.rb +++ b/lib/web_git/graph.rb @@ -29,6 +29,24 @@ def to_hash @full_list end + def to_array + # Each element is a branch log + # Each branch log has a starting commit and ending commit + # Each branch log only has commits that are unique to that branch + lists = @full_list.map{|l| l[:log] } + combined_branch = { branch: "ALL", head: "_" } + + + log_commits = [] + (lists.count - 1).times do |i| + log_hash = lists[i] + + log_commits = log_commits | log_hash + end + combined_branch[:log] = log_commits + log_commits + end + def has_untracked_changes? @git.diff.size > 0 end @@ -77,6 +95,7 @@ def build_array_of_commit_hashes commit[:formatted_date] = time_ago_in_words(git_commit_object.date) commit[:message] = git_commit_object.message commit[:author] = git_commit_object.author.name + commit[:branch_name] = @git.current_branch commit[:heads] = [] log_commits.push commit end From 8cd70ffd3bb9f47e23761cca44b6bab25af1f28d Mon Sep 17 00:00:00 2001 From: Jelani Woods Date: Sun, 21 Jun 2020 22:08:33 -0500 Subject: [PATCH 3/5] Kinda sorta got the information I need --- Gemfile.lock | 4 +- lib/web_git.rb | 5 +- lib/web_git/graph.rb | 150 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 80ed227..3cee973 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -24,7 +24,8 @@ GEM erubi (1.8.0) faraday (0.15.4) multipart-post (>= 1.2, < 3) - git (1.5.0) + git (1.7.0) + rchardet (~> 1.8) github_api (0.18.2) addressable (~> 2.4) descendants_tracker (~> 0.0.4) @@ -81,6 +82,7 @@ GEM rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) rake (12.3.2) + rchardet (1.8.0) rdoc (3.12.2) json (~> 1.4) rspec (3.5.0) diff --git a/lib/web_git.rb b/lib/web_git.rb index 2da569f..1a403fa 100644 --- a/lib/web_git.rb +++ b/lib/web_git.rb @@ -15,7 +15,10 @@ class Server < Sinatra::Base g = Git.open(working_dir) graph = WebGit::Graph.new(g) - graph.to_hash.to_json + # graph.find_common_shas.to_json + # graph.tree_traversal.to_json + graph.build_backwards.to_json + # graph.to_hash.to_json #sha = commit.sha.slice(0..7) # commit_date = Date.parse commit.date # strftime("%a, %d %b %Y, %H:%M %z") -> time_ago_in_words(commit_date) diff --git a/lib/web_git/graph.rb b/lib/web_git/graph.rb index 9156f62..41e5a6b 100644 --- a/lib/web_git/graph.rb +++ b/lib/web_git/graph.rb @@ -29,6 +29,156 @@ def to_hash @full_list end + def list_all_shas + @list = [] + branches = @git.branches.local.map(&:name) + branches.each do |branch_name| + branch = { name: branch_name } + @git.checkout(branch_name) + log = [] + @git.log.each do |git_commit_object| + sha = git_commit_object.sha.slice(0..7) + log.push sha + end + branch[:log] = log + @list.push branch + end + end + + def find_common_shas + list_all_shas + @keep_list = @list + new_list = [] + # Only need to compare to the master branch? + # master = @list + @list.each do |branch| + if branch[:name] == "master" + current_log = branch[:log] + other_branches = @list - [ branch ] + new_list.push({name: "master", log: current_log}) + p "Current Branch: #{branch[:name]}" + p "================================" + other_branches.each do |other_branch| + p "Other Branch: #{other_branch[:name]}" + new_branch = { name: other_branch[:name]} + branch_log = other_branch[:log] + + p "Current Log: #{current_log}" + p "Branch Log: #{branch_log}" + unique_commits = branch_log - current_log + p "Unique Log: #{unique_commits}" + new_branch[:log] = unique_commits + p "Parents" + @git.gcommit(unique_commits.first).parents.each do |gcommit| + p "---" + p gcommit.message + " " + gcommit.sha + p "---" + end + new_list.push new_branch + # current_log.each do |sha| + # end + end + p "================================" + puts "\n" * 3 + end + end + new_list + end + + def is_unique_sha?(sha, name, list) + # p "IS UNIQUE" + list.each do |branch| + if branch[:name] != name + # p "Branch name: #{branch[:name]}" + # p "(real)current: " + name + log = branch[:log] + # p "log" + # p log + # p " - " + sha + if log.include? sha + return false + end + end + end + true + end + + def get_parents(sha, name, list) + commit = @git.gcommit(sha) + parents = commit.parents + # if parents.size > 1 then it's a merge commit + if parents.size > 0 + # Find out if sha is unique, + # If not, branch is current + # Else branch is 'master' + branch_name = "master" + # p "SHA CLASSS" + # p sha.class + # p "#{sha}" + # puts "\n" * 3 + # p "====uniqueness=====" + if is_unique_sha?(sha, name, @list) + # p "IS UNIQUE" + branch_name = name + end + # p "====uniqueness=====" + # puts "\n" * 3 + + p "Commit: #{sha} - #{commit.message} - branch: #{branch_name}" + if parents.size > 1 + p "Merge Point #{parents.map{ |c| c.sha.slice(0..7)}.join(", ")}" + end + + parents.each do |parent| + get_parents(parent.sha.slice(0..7), name, list) + end + else + # It's the first commit + p "Commit: #{sha} - #{commit.message}" + return + end + end + + def build_backwards + # [{"name":"master","log":["3c391fc0","f0c357bb","64d6e333","f716b366"]},{"name":"c-branch","log":["ef99623c"]},{"name":"update","log":["bc9833b9"]}] + list = find_common_shas + + p "building..." + list.reverse.each do |branch| + name = branch[:name] + p "Branch: #{name}" + log = branch[:log] + # p log.last.class + # p @list + # p "[][][][]" + # p @keep_list + last = @git.gcommit(log.first) + # p "Last commit #{last.sha.slice(0..7)} - #{last.message}" + get_parents(last.sha.slice(0..7), name, @list) + + # TODO + # Create Hash of commits, ordered by date— + # { "47485296": { branch: "master", branches_to: [] }, "3b3aaccf": { branch: "master", branches_to: ["b-branch"]}, "4bb66595": {}, } + p "+++---" + end + p "======" + + [] + end + + def tree_traversal + tree = [] + @git.log.each do |git_commit_object| + sha = git_commit_object.sha.slice(0..7) + parents = git_commit_object.parents.map{ |parent| { sha: parent.sha, message: parent.message}} + git_tree = @git.gtree(git_commit_object.sha) + children = git_tree.children#.map{ |child| { sha: child.sha, message: child.message}} + object = {message: git_commit_object.message, sha: sha, parents: parents, children: children} + tree.push object + end + tree + end + def to_array # Each element is a branch log # Each branch log has a starting commit and ending commit From 9fd731059593a3ccb577dd5fd11aa81117b5d753 Mon Sep 17 00:00:00 2001 From: Jelani Woods Date: Mon, 22 Jun 2020 12:33:26 -0500 Subject: [PATCH 4/5] Demo of graphing with the JS lib --- lib/views/log.erb | 80 ++++++++++++++++++++++++++++++++++++++++++++ lib/web_git.rb | 6 ++-- lib/web_git/graph.rb | 57 ++++++++++++++++++++++++++++--- 3 files changed, 136 insertions(+), 7 deletions(-) create mode 100644 lib/views/log.erb diff --git a/lib/views/log.erb b/lib/views/log.erb new file mode 100644 index 0000000..fb573fe --- /dev/null +++ b/lib/views/log.erb @@ -0,0 +1,80 @@ + + + + <% created_branches = []%> + <% @graph.commit_order.each do |sha| %> + <% commit_info = @graph.graph_order[sha] %> + <% commit_info %> + <% if @graph.commit_order.index(sha) == 0 %> + var master = gitgraph.branch("master"); +
+ gitgraph.commit({ sha1: "<%= sha %>"", message: ""}}); +
+ <% created_branches.push "master" %> + <% else %> + <% if !created_branches.include? commit_info[:branch] %> + const <%= commit_info[:branch] %> = gitgraph.branch("<%= commit_info[:branch] %>"); +
+ <% end %> + <% created_branches.push commit_info[:branch] %> + <%= commit_info[:branch] %>.commit({message: "", sha1: "<%= sha %>"}); + <% if commit_info[:branches_to].size > 0 %> + <% commit_info[:branches_to].each do |branch| %> + const <%= branch %> = gitgraph.branch("<%= branch %>"); +
+ <% created_branches.push branch %> + <% end %> + <% end %> + +
+ <% end %> + <% end %> diff --git a/lib/web_git.rb b/lib/web_git.rb index 1a403fa..6dd274d 100644 --- a/lib/web_git.rb +++ b/lib/web_git.rb @@ -14,17 +14,17 @@ class Server < Sinatra::Base working_dir = File.exist?(Dir.pwd + "/.git") ? Dir.pwd : Dir.pwd + "/.." g = Git.open(working_dir) - graph = WebGit::Graph.new(g) + @graph = WebGit::Graph.new(g) # graph.find_common_shas.to_json # graph.tree_traversal.to_json - graph.build_backwards.to_json + @graph.build_backwards#.to_json # graph.to_hash.to_json #sha = commit.sha.slice(0..7) # commit_date = Date.parse commit.date # strftime("%a, %d %b %Y, %H:%M %z") -> time_ago_in_words(commit_date) # * 76eff73 - Wed, 11 Mar 2020 19:58:21 +0000 (13 days ago) (HEAD -> current_branch) # | blease - Jelani Woods - + erb :log # " * " + sha + " - " + commit_date + " (" + time_ago_in_words(commit_date) + ") " + "\n\t| " + commit.message end diff --git a/lib/web_git/graph.rb b/lib/web_git/graph.rb index 41e5a6b..5c55c17 100644 --- a/lib/web_git/graph.rb +++ b/lib/web_git/graph.rb @@ -6,11 +6,15 @@ class Graph require "action_view/helpers" include ActionView::Helpers::DateHelper attr_accessor :heads + attr_reader :graph_order + attr_reader :commit_order def initialize(git) @git = git @full_list = [] @heads = {} + @graph_order = {} + @commit_order = [] end def to_hash @@ -103,6 +107,19 @@ def is_unique_sha?(sha, name, list) true end + def find_other_branch_names(sha, name, list) + branch_names = [] + list.each do |branch| + if branch[:name] != name + log = branch[:log] + if log.include? sha + branch_names.push branch[:name] + end + end + end + branch_names + end + def get_parents(sha, name, list) commit = @git.gcommit(sha) parents = commit.parents @@ -123,7 +140,20 @@ def get_parents(sha, name, list) end # p "====uniqueness=====" # puts "\n" * 3 - + if @graph_order.keys.include? sha + + @graph_order[sha][:branches_to] = find_other_branch_names(sha, name, @list) + p @graph_order[sha][:branches_to] + else + @graph_order[sha] = { branch: branch_name, branches_to: [] } + end + if @commit_order.include? sha + i = @commit_order.index(sha) + @commit_order.delete_at(i) + @commit_order.push sha + else + @commit_order.push sha + end p "Commit: #{sha} - #{commit.message} - branch: #{branch_name}" if parents.size > 1 p "Merge Point #{parents.map{ |c| c.sha.slice(0..7)}.join(", ")}" @@ -134,7 +164,15 @@ def get_parents(sha, name, list) end else # It's the first commit - p "Commit: #{sha} - #{commit.message}" + if @commit_order.include? sha + i = @commit_order.index(sha) + @commit_order.delete_at(i) + @commit_order.push sha + else + @commit_order.push sha + end + @graph_order[sha] = { branch: "master", branches_to: [] } + p "Commit: #{sha} - #{commit.message} - branch: master" return end end @@ -155,14 +193,25 @@ def build_backwards last = @git.gcommit(log.first) # p "Last commit #{last.sha.slice(0..7)} - #{last.message}" get_parents(last.sha.slice(0..7), name, @list) - + p "_________________________" + p "_________________________" + # p @graph_order # TODO # Create Hash of commits, ordered by date— # { "47485296": { branch: "master", branches_to: [] }, "3b3aaccf": { branch: "master", branches_to: ["b-branch"]}, "4bb66595": {}, } p "+++---" end p "======" - + p @commit_order = @commit_order.reverse + # ["f62e91d6", "4bb66595", "de987471", "3b3aaccf", "47485296"] + @commit_order.each do |sha| + commit_info = @graph_order[sha] + if commit_info[:branches_to].size > 0 + p "#{sha} - #{commit_info[:branch]}, branches to #{commit_info[:branches_to].join(" ,")}" + else + p "#{sha} - #{@graph_order[sha][:branch]}" + end + end [] end From 2cbb969e5b76b7a2660c8f42074b8609476476f1 Mon Sep 17 00:00:00 2001 From: Jelani Woods Date: Mon, 22 Jun 2020 17:15:26 -0500 Subject: [PATCH 5/5] Potentially made merging work --- lib/views/log.erb | 88 ++++++++++++++++++++++++++++++++++---------- lib/web_git/graph.rb | 46 ++++++++++++++++++++--- 2 files changed, 110 insertions(+), 24 deletions(-) diff --git a/lib/views/log.erb b/lib/views/log.erb index fb573fe..184bc79 100644 --- a/lib/views/log.erb +++ b/lib/views/log.erb @@ -15,40 +15,43 @@ <% if @graph.commit_order.index(sha) == 0 %> var master = gitgraph.branch("master"); - gitgraph.commit({ sha1: "<%= sha %>", message: ""}); + gitgraph.commit({ sha1: "<%= sha %>", message: "<%= commit_info[:message] %>", author: "<%= commit_info[:author] %>"}); <% created_branches.push "master" %> <% else %> <% if !created_branches.include? commit_info[:branch] %> const <%= commit_info[:branch].gsub("-", "_") %> = gitgraph.branch("<%= commit_info[:branch].gsub("-", "_") %>"); - <% end %> + <% created_branches.push commit_info[:branch] %> - <%= commit_info[:branch].gsub("-", "_") %>.commit({message: "", sha1: "<%= sha %>"}); + <% if commit_info[:merge_between].size > 0 %> + <% merge_commits = commit_info[:merge_between] %> + <% branch_1 = @graph.graph_order[merge_commits.first][:branch].gsub("-", "_") %> + <% branch_2 = @graph.find_merging_branch_name(merge_commits.first, merge_commits.last).gsub("-", "_") %> + <%= branch_2 %>.merge( + <%= branch_1%>, + { + sha1: "<%= sha %>", + message: "<%= commit_info[:message] %>", + author: "<%= commit_info[:author] %>" + } + ); + <% else %> + <%= commit_info[:branch].gsub("-", "_") %>.commit({message: "<%= commit_info[:message] %>", sha1: "<%= sha %>", author: "<%= commit_info[:author] %>"}); + <% end %> <% if commit_info[:branches_to].size > 0 %> <% commit_info[:branches_to].each do |branch| %> - const <%= branch.gsub("-", "_") %> = gitgraph.branch("<%= branch.gsub("-", "_") %>"); - - <% created_branches.push branch %> + <% if !created_branches.include? branch %> + const <%= branch.gsub("-", "_") %> = gitgraph.branch("<%= branch.gsub("-", "_") %>"); + + <% created_branches.push branch %> + <% end %> <% end %> <% end %> <% end %> <% end %> - - // gitgraph.commit("My first commit"); // 1 commit upon HEAD - // var develop = gitgraph.branch("develop"); // New branch from HEAD - // var myfeature = develop.branch("myfeature"); // New branch from develop - // develop.commit("Develop a feature - part 1"); - // develop.commit("Develop a feature - part 2"); - - // master.commit({message: "Fast bugfix", author: "John Fixer"}); - // myfeature.commit({message: "New cool feature", author: "John Feature"}); - - // develop.merge(master); - // myfeature.merge(master); - // master.commit({message: "Release of version 0.1", tag: "0.1", author: "John Releaser", sha1: "abcdef0"}); <% created_branches = []%> <% @graph.commit_order.each do |sha| %> @@ -72,9 +75,56 @@ const <%= branch %> = gitgraph.branch("<%= branch %>");
<% created_branches.push branch %> +
<% end %> <% end %>
<% end %> <% end %> +
+ + + <% created_branches = []%> + <% @graph.commit_order.each do |sha| %> + <% commit_info = @graph.graph_order[sha] %> + <% commit_info %> + <% if @graph.commit_order.index(sha) == 0 %> + var master = gitgraph.branch("master"); +
+ gitgraph.commit({ sha1: "<%= sha %>", message: "<%= commit_info[:message] %>", author: "<%= commit_info[:author] %>"}); +
+ + <% created_branches.push "master" %> + <% else %> + <% if !created_branches.include? commit_info[:branch] %> + const <%= commit_info[:branch].gsub("-", "_") %> = gitgraph.branch("<%= commit_info[:branch].gsub("-", "_") %>"); +
+ <% end %> + + <% created_branches.push commit_info[:branch] %> + <% if commit_info[:merge_between].size > 0 %> + <% merge_commits = commit_info[:merge_between] %> + <%# @graph.graph_order %> + <% branch_1 = @graph.graph_order[merge_commits.first][:branch] %> + <% branch_2 = @graph.find_merging_branch_name(merge_commits.first, merge_commits.last)%> + <%= branch_1 %>.merge(<%= branch_2%>); +
+ <% else %> + <%= commit_info[:branch].gsub("-", "_") %>.commit({message: "<%= commit_info[:message] %>", sha1: "<%= sha %>", author: "<%= commit_info[:author] %>"}); +
+ <% end %> + <% if commit_info[:branches_to].size > 0 %> + <% commit_info[:branches_to].each do |branch| %> + <% if !created_branches.include? branch %> + const <%= branch.gsub("-", "_") %> = gitgraph.branch("<%= branch.gsub("-", "_") %>"); +
+ + <% created_branches.push branch %> + <% end %> + <% end %> + <% end %> + + + <% end %> + <% end %> diff --git a/lib/web_git/graph.rb b/lib/web_git/graph.rb index 5c55c17..11dcd64 100644 --- a/lib/web_git/graph.rb +++ b/lib/web_git/graph.rb @@ -120,6 +120,22 @@ def find_other_branch_names(sha, name, list) branch_names end + def find_merging_branch_name(first, last) + list = @list + # Start with two commit shas + # f0c357b, 64d6e33 + # Find branch with f0c357b, (Should already be able to find this one) + # Find branch with 64d6e33, but NOT f0c357b + branch1 = "" + branch2 = "" + + list.each do |branch| + if !branch[:log].include?(first) && branch[:log].include?(last) + return branch[:name] + end + end + end + def get_parents(sha, name, list) commit = @git.gcommit(sha) parents = commit.parents @@ -141,11 +157,23 @@ def get_parents(sha, name, list) # p "====uniqueness=====" # puts "\n" * 3 if @graph_order.keys.include? sha - - @graph_order[sha][:branches_to] = find_other_branch_names(sha, name, @list) - p @graph_order[sha][:branches_to] + p "FINDING OTHER BRANCH NAMES" + # if already have a branch to, maybe DON't add another one + other_branch_tos = @graph_order.keys.map do |other_sha| + @graph_order[other_sha][:branches_to] + end + p "//////////" + p other_branch_tos.reduce(&:+) + p "//////////" + if !other_branch_tos.reduce(&:+).include?(branch_name) + p "First one" + @graph_order[sha][:branches_to] = find_other_branch_names(sha, name, @list) + p @graph_order[sha][:branches_to] + else + p "Don't you do it!" + end else - @graph_order[sha] = { branch: branch_name, branches_to: [] } + @graph_order[sha] = { branch: branch_name, branches_to: [], merge_between: [], message: commit.message, author: commit.author.name } end if @commit_order.include? sha i = @commit_order.index(sha) @@ -156,7 +184,11 @@ def get_parents(sha, name, list) end p "Commit: #{sha} - #{commit.message} - branch: #{branch_name}" if parents.size > 1 + @graph_order[sha][:merge_between] = parents.map{ |c| c.sha.slice(0..7)} p "Merge Point #{parents.map{ |c| c.sha.slice(0..7)}.join(", ")}" + first = parents.first.sha.slice(0..7) + last = parents.last.sha.slice(0..7) + @graph_order[last][:branch] = find_merging_branch_name(first, last) end parents.each do |parent| @@ -171,7 +203,7 @@ def get_parents(sha, name, list) else @commit_order.push sha end - @graph_order[sha] = { branch: "master", branches_to: [] } + @graph_order[sha] = { branch: "master", branches_to: [], merge_between: [], message: commit.message, author: commit.author.name } p "Commit: #{sha} - #{commit.message} - branch: master" return end @@ -192,6 +224,10 @@ def build_backwards # p @keep_list last = @git.gcommit(log.first) # p "Last commit #{last.sha.slice(0..7)} - #{last.message}" + exclude_branches = {} + # Looks like + # { "master": [], "update": [], "c-branch": ["master", "update"]} + # On the basis that all of master exists in c-branch currently get_parents(last.sha.slice(0..7), name, @list) p "_________________________" p "_________________________"