November 12, 2020
I’ve recently begun using Git at a slightly higher level than I have before, which isn’t saying much, and with that I’ve discovered how wonderful patch files are to use. With that I’ve wanted a way to quickly save all the changes I’ve made to files into patch files on a per changed file basis.
Though I am aware of git-stash it does not quite serve my quite probably broken needs, so I wondered if there was a way to quickly get patch files created for all of the files I changed prior to, for example, completely removing the repository from my machine. Given that Git is so damn expansive in its sub-commands and various parameters, I’ve most likely overlooked an existing command that does what I want (and better), but let’s pretend I am a unique snowflake and that no one has wanted to do this exactly this way.
Upon googling I found Remy van Elst’s blog post about splitting a file into blocks and doing something with those blocks, which pretty much got me 90% of what I wanted without spending more time than necessary on this bike shed of a venture. Here is the code as it stands currently:
OLDIFS=$IFS
IFS=';'
blocks=$(git diff | sed -n '/diff/,/(diff|$)/ {/diff / s/^/\;/; p}')
for block in ${blocks#;}; do
echo "$block" > $(echo "$block" | head -n 1 | rev | cut -d "/" -f 1 | rev).patch
done
IFS=$OLDIFS
I won’t go over lines 1, 2, 3, 4, 7 as those are explained well enough in the linked blog post above. The only difference is that I am executing git diff
and passing the word “diff” as the starting marker and (diff|$)
as the ending marker. The ending marker can be read as: match either the word “diff” or the dollar-symbol denoting the end of the string.
The 10% that I added is in line number 5 where I just echo the contents of the block
variable and form the name of the patch file by:
echo "$block" | head -n 1
;
diff --git a/my-repository/Get-Good.ps1 b/my-repository/Get-Good.ps1
rev
;
1sp.dooG-teG/yrotisoper-ym/b 1sp.dooG-teG/yrotisoper-ym/a tig-- ffid
cut -d "/" -f 1
;
1sp.dooG-teG
rev
again to return it into its original form;
Get-Good.ps1
.patch
to the very end to uniquely identify it as a patch file.This works with a single changed file and with multiple, so everything that is needed is to save that code as a function within your .bashrc
or .bash_aliases
(the former of which is then sourced) or to run this one-liner:
OLDIFS=$IFS; IFS=';' blocks=$(git diff | sed -n '/diff/,/(diff|$)/ {/diff / s/^/\;/; p}'); for block in ${blocks#;}; do echo "$block" > $(echo "$block" | head -n 1 | rev | cut -d "/" -f 1 | rev).patch; done; IFS=$OLDIFS
« PreviousNext »