There is no perfect solution, but you can get close, perhaps close enough.
Be sure to start with a clean work tree and index tree (see require_clean_work_tree in git-sh-setup ).
For each candidate $branch , which can be removed:
- Find your merge target (presumably
merge_target=$(git config --get branch.${branch}.merge) ). Check the merger target. --no-commit with --no-commit ; or in step 1, check with --detach so that you get a commit that you can leave if the merge is successful.- Check if git merge matches, and if so, does the current tree match the previous tree, i.e. does not make any changes. If you can verify exact matches, and if you allow committing (via
--detach ), you can do this last test very simply, without any difference: run both git rev-parse HEAD^{tree} and git rev-parse HEAD^^{tree} 1 and see if they produce the same hash. If you do not allow commit, you can git diff execute the current ( HEAD ) against the proposed merge. If you need to remove some noise from diff (for example, configuration files that shouldn't be, but in commits anyway), this gives you room for that. - Reset (
git merge --abort; git reset --hard HEAD; git clean -f or similar, depending on how you decide to implement steps 1-3). It just means that your work tree and index are cleared again for the next pass. - If the merge in step 3 worked and did not introduce any changes, you can delete the local branch. Otherwise, save it.
In essence, this “actually merging and see what happens” is simply fully automated.
1 These notations look a little strange, but it's just HEAD^ - the first parent element of HEAD - after ^{tree} . Alternate spellings may be easier to read: HEAD~1^{tree} or ${merge_target}^tree , where ${merge_target} is the branch you checked in step 1. Note that this assumes the merge completed successfully. The merge result is in git merge exit status: a null value succeeds, a nonzero tool does not work, and needs manual help, presumably due to a merge conflict.
torek
source share