I have written a series of git commits, with awful code formatting.
Before I push them to github, I want to run git-clang-format
on each commit, to get a nicely formatted code in my history.
Is there some combination of rebase
and git-clang-format
which will accomplish this?
That looks like a job for git filter-branch
, which can rewrite the commits you want. Since those commits are not yet pushed, changing their content (and, consequently their SHA1) is not a big deal.
And the effect is similar to what a rebase or cherry-picking would do, except you can run any command for each commit being replayed.
You can run a filter-branch
over the last few commits:
See "Reformatting Your Codebase with git filter-branch
", by Elliot Chance
git filter-branch --tree-filter 'git-clang-format' -- <SHA1>..HEAD
Considering the git-clang-format
syntax, you can apply it only on the changed files in each commits.
For instance, for .cpp
files:
git filter-branch --tree-filter 'git-clang-format $(\
git diff-index --diff-filter=AM --name-only $GIT_COMMIT |\
grep .cpp)' -- <SHA1>..HEAD
Update 2017, with Git 2.14.x/2.15 (Q4 2017) you have an illustration:
See commit 2118805, commit 6134de6 (14 Aug 2017) by Brandon Williams (mbrandonw
).
(Merged by Junio C Hamano -- gitster
-- in commit a36f631, 25 Sep 2017)
Makefile: add style build rule
Add the '
style
' build rule which will rungit-clang-format
on the diff between HEAD and the current worktree.
The result is a diff of suggested changes.
.PHONY: style
style:
git clang-format --style file --diff --extensions c,h
I do this manually right now so the format does not mess up anything. Example: header reorganization is a possibility which can cause compile failures.
Steps start from latest commit. If you start at HEAD~# then the changes almost never unless they are atomic and unrelated. git clang-format only changes the code you changed(and related code blocks) but not other non-touched code.
(you can do this manually on a command line but for some reason I still do this with the editing).
You then repeat the steps for HEAD~2, HEAD~3 until you have finished working your way up to the chain.
Some Notes on this. clang-format will change the same code over and over again in certain cases. It has gotten much rarer but have to ignore them at times.
If you want to apply clang-format only to the changed lines in each commit do the following:
# The first commit you want to edit.
# You can use the following command if it’s a child of origin/master.
export FIRST_COMMIT=$(git rev-list --ancestry-path origin/master..HEAD | tail -n 1)
git filter-branch --tree-filter 'git-clang-format $FIRST_COMMIT^' -- $FIRST_COMMIT..HEAD
This will do the following for each commit:
FIRST_COMMIT
’s parent (e.g. origin/master
).
(NOTE: If you only were only to compute the diff to the current commits parent you may undo clang-format changes done on other commits!)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With