dev/diff/ GitDiff
Something I found very useful when following these videos was using git diff
between consecutive commits. I wrote a simple python script to automate this, which I'll share here in case anybody wants it.
first, run
gitdiff -g # put list of commits in 'commits'
gitdiff -g commit_filename # put list of commits in 'commit_filename'
to create a list of commits.
There are two scripts, one generates a directory of individual diff files, the other generates a markdown file like the source of TapSynthGitDiff.
The code
Apologies for using terse variable names. A script like this is small enough that I can easily keep track of what one-letter variable stands for what, kind of like reading a maths proof.
The result of that is that you'll have either a bunch of files in the diffs/
folder you created which you can peruse to see the actual changes from step to step, or a single markdown file suitable for putting through e.g. Pandoc or Parsedown. My intent is to add text notes to these files as I read through them. The beauty of this is that you're no longer constrained to the pace of the videos, which may be slower or faster than your taste, and you don't have the 'I missed that — rewind' problem that you always get with coding walkthrough videos.
Indeed this works with any git repo where there is a single chain of commits. (For anything with more complicated branching structure, you'll need to work out a sequence of commits to break down into steps.)
gitdiff
Run with
gitdiff # look for commits in 'commits'
gitdiff commit_filename # look for commits in 'commit_filename'
Generates director of individual diffs
#!/usr/bin/env python
# git log | grep commit > commits
from subprocess import run, PIPE
import sys
import os
args = sys.argv[1:]
if len(args) > 0:
if args[0] == "-g":
if len(args) > 1:
cfn = args[1]
else:
cfn = "commits"
m = run(["git","log"],stdout=PIPE)
a = m.stdout.decode().splitlines()
b = [x for x in a if "commit" in x]
with open(cfn,"wt") as f:
f.write("\n".join(b))
print(f"Generated {cfn}")
exit(0)
else:
cfn = args[0]
else:
cfn = "commits"
try:
commits = open(cfn).read().rstrip().splitlines()
except Exception as e:
print(f"Cannot read commits file '{cfn}' -- {e}")
print("Create with:")
print("git log | grep commit > commits")
print("and if necessary edit the list")
print(f"or use {sys.argv[0]} -g <commits filename>")
exit(1)
commits = list(reversed(commits))
l = len(commits) - 1
c = lambda t: t.split(" ")[1]
od = f"diffs_{cfn}"
os.makedirs(od,exist_ok=True)
for i in range(l):
a = c(commits[i])
b = c(commits[i+1])
with open(f"{od}/commits_{i:02d}_{a[:6]}_{b[:6]}.txt","wt") as f:
m = run(["git","diff",a,b],stdout=PIPE)
s = m.stdout.decode()
print(f"Diff {i}: {a} to {b}")
print(f"Diff {i}: {a} to {b}",file=f)
print(s,file=f)
gitdiffs_md
Run with
gitdiff_md # look for commits in 'commits'
gitdiff_md commit_filename # look for commits in 'commit_filename'
Generates single markdown file
#!/usr/bin/env python
# git log | grep commit > commits
from subprocess import run, PIPE
import sys
import os
args = sys.argv[1:]
if len(args) > 0:
if args[0] == "-g":
if len(args) > 1:
cfn = args[1]
else:
cfn = "commits"
m = run(["git","log"],stdout=PIPE)
a = m.stdout.decode().splitlines()
b = [x for x in a if "commit" in x]
with open(cfn,"wt") as f:
f.write("\n".join(b))
print(f"Generated {cfn}")
exit(0)
else:
cfn = args[0]
else:
cfn = "commits"
try:
commits = open(cfn).read().rstrip().splitlines()
except Exception as e:
print(f"Cannot read commits file '{cfn}' -- {e}")
print("Create with:")
print("git log | grep commit > commits")
print("and if necessary edit the list")
print(f"or use {sys.argv[0]} -g <commits filename>")
exit(1)
commits = list(reversed(commits))
l = len(commits) - 1
c = lambda t: t.split(" ")[1]
ofn = f"{cfn}.md"
md = []
def procdiff(s):
ls = s.splitlines()
h = ls[0]
r = ls[1:]
t = []
ax = []
for x in r:
if x.startswith("diff --git"):
if len(ax) > 0:
t.append(ax)
ax = []
ax.append(x)
if len(ax) > 0:
t.append(ax)
return h,t
for i in range(l):
a = c(commits[i])
b = c(commits[i+1])
m = run(["git","diff",a,b],stdout=PIPE)
s = m.stdout.decode()
h,t = procdiff(s)
md.append(f"<h4 class='diffhead'>Diff 0: {a} to {b}</h4>\n")
for x in t:
md.append(f"""<div class='pre1'>{x[0]}
{x[1]}
</div>
""")
md.append("```diff")
for y in x[2:]:
md.append(y)
md.append("```\n")
with open(ofn,"wt") as f:
f.write("\n".join(md))