Last active
September 18, 2018 05:24
-
-
Save dduan/eea4aaace72cf9000b87db6272b94640 to your computer and use it in GitHub Desktop.
Generate commit for each staged file, such that each commit is a `--fixup` to the commit said file was last changed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
Generate commit for each staged file, such that each commit is a `--fixup` to | |
the commit said file was last changed. | |
NOTE: this command will unstage all files. It also does not disninguish staged | |
and unstaged potion of the same file. | |
USAGE: stage files you want to commit, run this command. Interactive rebase with | |
autosquash: `git rebase -i --autosquash BASE` | |
WHY: sometimes you want to change a bunch of files and distribute changes to | |
each file to recent history of your branch. This happens when you have | |
a list of commit in a pull request you want to end up neatly in history, | |
but you need to make some last minutes changes. | |
""" | |
from subprocess import (call, check_output) | |
# list paths for cached files | |
cached_file_paths = check_output(['git', 'diff', '--cached', '--name-only']) | |
new_commits = [] | |
for file_path in [p for p in cached_file_paths.split('\n') if p]: | |
# get SHA for the last commit this file is changed | |
latest_sha = check_output(['git', 'log', '-n', '1', '--pretty=format:%H', '--', file_path]) | |
call(['git', 'reset', 'HEAD', file_path]) | |
# ignore files that doesn't have a history | |
if not latest_sha: | |
continue | |
new_commits.append((file_path, latest_sha)) | |
# unstage everything for safety measures | |
call(['git', 'reset', 'HEAD', '.']) | |
for file_path, sha in new_commits: | |
# stage file | |
call(['git', 'add', file_path]) | |
# create a fixup commit | |
call(['git', 'commit', '--fixup', sha]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@dduan super useful gist. Thanks for writing it!
If you use
--name-status
git diff option, then you can also make it work for file renames, by grouping both the old and new file name in the same--fixup
Here is how I did it by nodeifying your python script.