Skip to content

Instantly share code, notes, and snippets.

@aslakhellesoy
Last active January 22, 2020 12:52
Show Gist options
  • Save aslakhellesoy/e0a8f57c9b8c132fe66ede410749a6d5 to your computer and use it in GitHub Desktop.
Save aslakhellesoy/e0a8f57c9b8c132fe66ede410749a6d5 to your computer and use it in GitHub Desktop.
Extract old and new versions of specific files throughout git history
#!/usr/bin/env bash
#
# Run this script from the root of a git repo to create directories containing
# the old and new version of a .feature file.
#
# A directory will be created for each commit that modifies a .feature file,
# and inside this directory there will be a directory with the name of the file.
# Finally, inside that directory there will be a `new` and `old` file showing
# the contents before and after the commit.
#
# The commit directories are prefixed with the unix timestamp of the commit.
# This makes it possible to sort them in chronological order during further processing.
#
# Example:
#
# tmp/
# ├── 1445335992-b22c74de8d6c2667b715ad47e1f190a9b23ce58d
# │   └── features
# │   └── publish_features.feature
# │   ├── new
# │   └── old
# ├── 1453378524-b6525f8ef499889d8dcceb9eda56de1ad0e75315
# │   └── features
# │   ├── create_projects.feature
# │   │   ├── new
# │   │   └── old
# │   └── publish_features.feature
# │   ├── new
# │   └── old
# └── 1459348969-cf95d79349a24eeb68f47528a6e25189b180fc6b
#    └── features
#    └── publish_features.feature
#    ├── new
#    └── old
#
#
#
out_dir="./tmp"
# Loop over all commit SHAs, starting with the oldest one
git log --reverse --reflog --pretty=format:"%H" | \
while read -r commit; do
# Loop over all feature files that were modified in this commit
git diff-tree -r ${commit} | \
grep "\.feature$" | \
grep --invert-match "0000000000000000000000000000000000000000" | \
while read -r blob_line; do
# Create a directory for the commit SHA followed by the filename
path=$(echo "${blob_line}" | cut -d$'\t' -f 2)
timestamp=$(git show -s --format=%ct ${commit})
dir="${out_dir}/${timestamp}-${commit}/${path}"
mkdir -p "${dir}"
# Write the old and new file
old_oid=$(echo "${blob_line}" | cut -d' ' -f3)
new_oid=$(echo "${blob_line}" | cut -d' ' -f4)
git show "${old_oid}" > "${dir}/old"
git show "${new_oid}" > "${dir}/new"
# Print some status
echo "${commit} ${path}"
done
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment