问题
I wrote a node module that uses git to make a bunch of commits from time to time. Considering the commits are better if grouped into one single commit, I'd like to use "git rebase -i" to squash them into one.
However squashing is only possible in interactive mode, which means I need to manually edit the lines in the editor that pops up when "git rebase -i" is called. I would like to know if it is possible to do this process programatically? So for example when the user calls "save" function my module would make a bunch of commits, and then automatically squash them together.
UPDATE
To be more precise of what I'm doing, when the "save" function is called, it is passed a bunch of commits to be "publish". My module will then cherry pick those commits and put them into the "publish" branch. This is a single "publish" action, but it generates a bunch of commits on the "publish" branch. What I wanna do is to squash the commits on the publish, so when I do "git log" all I see is "publish version 1", "publish version 2" etc, instead of 5 or 10 commits per publish action.
回答1:
After seeing your update to your question, one of the two options below may work, depending on your usage:
The first (and simpler) case is where your unpublished work is always a single sequence of commits, and the published work is on the same branch, but a bit further behind:
- You have an
unpublished
branch and apublished
branch. The latter is contained within the former (i.e. some number of commits behind). - The save action means that a hash
abcdef
fromunpublished
should now be the HEAD ofpublished
. - It performs
git checkout published && git merge --ff-only abcdef
. - This causes
published
to fast-forward to that commit.
The second is where the commits that can be published are not necessarily a linear sequence. This becomes a little more complicated as if you reorder commits, you may have to resolve conflicts that arise. I would solve that in the following way:
- Assume again that there are
unpublished
andpublished
branches. - The save action comprises some hashes from
unpublished
. - It should create a new, temporary branch like
publish-2013-04-15-001
from the currentpublished
branch (the name of the new branch is largely irrelevant, as long as it's unique/new). - Perform
git cherry-pick <hash>
for each hash that should be saved. (If there are multiple commits, this is where you could get conflicts and may need to resolve them somehow.) - Once done, check out
published
branch. - Perform
git merge --squash -m 'Publish version <n>' publish-2013-04-15-001
. - (Optional) delete the temporary branch.
Since the second option introduces more complication, there are other options that you might want to consider to make it easier to debug the published process:
- Should I keep the temporary branches around for tracking/logging?
- Could the individual commits be kept separate on the merged branch (leave out
--squash
)? - If so, you could identify the save by forcing a merge commit (
--no-ff
).
EDIT: Here's an example using --no-ff
. Each version $N
does the following:
git checkout -b publish-$N published
# cherry-pick commits
git checkout published && git merge --no-ff publish-$N -m "Publish version $N"

来源:https://stackoverflow.com/questions/16019900/programmatically-use-git-rebase-i