At work, we are asked to "squash" our commits once our pull-request is approved
for merge. This makes the
git log output much cleaner, since there
are only two commits per feature (one for the work, and one merging that work).
master hasn't been modified since you started work, this is painless.
However, if it has, there's a chance you'll need to fix merge conflicts --
often multiple times on the same files, as git re-applies each commit. This
is frustrating and unnecessary.
If you had nothing better to do, an easy "manual" way to do this would be:
- check out a copy of the master branch
git diff --name-only new_branchto see what was changed
- for each file, check whether the file was added, modified, or deleted.
- for each deleted file, delete from current repo
- for each added or modified file,
git checkout new_branch -- filename
Then just commit theses changes and you'll be all done.
Here's a script that does exactly that:
#!/usr/bin/env bash current=$(git rev-parse --abbrev-ref HEAD) older="$1" if [ "$older" == "" ]; then echo "must pass in branch name to rebase from" exit fi git checkout $older || exit git checkout -b rebase || exit git diff --name-only $current | \ while read filename; do git checkout $current -- $filename || rm $filename done git status echo "Done. WARNING: Review carefully, commit, and diff against $current" echo "before deleting $current."
Here's an annotated version.
#!/usr/bin/env bash # This line gets the currently-checked-out git branch. current=$(git rev-parse --abbrev-ref HEAD) # This is the first command-line argument, so you'd run this like so if you # wanted to rebase from master: # rebase master older="$1" # If they forget to pass in a branch from which to rebase: if [ "$older" == "" ]; then echo "must pass in branch name to rebase from" exit fi # Check out the branch to rebase from. If it fails for some reason # (branch doesn't exist, for example), it will quit. git checkout $older || exit # Check out a branch named "rebase" as a temporary branch. If that's not # possible (branch already exists, for example), it will quit. git checkout -b rebase || exit # Get a list of files that differ. git diff --name-only $current | \ while read filename; do # Check out the file. If the checkout fails (doesn't exist in the # $current branch, it was deleted in the newer branch, so delete # here. This will show error messages to the user while this script # is running, but that's okay. git checkout $current -- $filename || rm $filename done # Show the user the status of the uncommitted rebase branch. git status echo "Done. WARNING: Review carefully, commit, and diff against $current" echo "before deleting $current."