Combine or rebase an arbitrarily large number of commits

前端 未结 3 891
伪装坚强ぢ
伪装坚强ぢ 2020-12-28 11:46

Let\'s say my local git log shows:

739b36d3a314483a2d4a14268612cd955c6af9fb a
...
c42fff47a257b72ab3fabaa0bcc2be9cd50d5c89 x
c4149ba120b30955a92         


        
3条回答
  •  没有蜡笔的小新
    2020-12-28 12:07

    "Easiest" is always a bit tricky. Interactive rebase will let you squash everything, and is "easy" by some measure.

    Another "easy" way, which looks a bit complicated, is to use a "squash merge" (which is not an actual merge at all, but does use the same underlying code as git merge, so it's done with the same command). Let's say you're on branch devel whose upstream is origin/devel. First we'll rename devel to devel-full to indicate that it's the one with the full sequence of commits. Then we'll create a new devel tracking origin/devel, and "squash-merge" devel-full:

    git branch -m devel devel-full
    git checkout --track origin/devel
    git merge --squash devel-full
    git commit
    

    You have to separately git commit as --squash inhibits the commit that git merge normally makes.

    Yet a third easy (?) but slightly scary way is to check out the tip version and commit it. Again, assuming devel as before, we move the "full develoment" branch-name out of the way and make a new local branch to make the new commit on. This time instead of git merge --squash, though, we use two commands before git commit:

    git branch -m devel devel-full
    git checkout --track origin/devel
    git rm -rf .                      # assumes you're in the top directory
    git checkout devel-full -- .
    git commit
    

    The git rm -rf . schedules (in the index/staging-area) every single file to be removed, but then the git checkout devel-full -- . tells git to re-populate the index/staging-area with every single file that exists at the tip of devel-full. So this means "make the tree for the next commit, look exactly like the tree for the tip of devel-full".

    (The remove-and-re-create method works for one case where merge --squash does not: specifically, it works for "replacing" the tip of one branch with the tip of another, even if the two branches are not related and hence not merge-able. Otherwise merge --squash is one step shorter, and definitely not as scary looking, at least!)

    Both of these other "easy" (?) ways leave you with a branch with the full development history. If you want it, great! If not, you have to delete it.

提交回复
热议问题