When do you use Git rebase instead of Git merge?

后端 未结 17 2384
独厮守ぢ
独厮守ぢ 2020-11-21 11:25

When is it recommended to use Git rebase vs. Git merge?

Do I still need to merge after a successful rebase?

相关标签:
17条回答
  • 2020-11-21 12:25

    Some practical examples, somewhat connected to large scale development where Gerrit is used for review and delivery integration:

    I merge when I uplift my feature branch to a fresh remote master. This gives minimal uplift work and it's easy to follow the history of the feature development in for example gitk.

    git fetch
    git checkout origin/my_feature
    git merge origin/master
    git commit
    git push origin HEAD:refs/for/my_feature
    

    I merge when I prepare a delivery commit.

    git fetch
    git checkout origin/master
    git merge --squash origin/my_feature
    git commit
    git push origin HEAD:refs/for/master
    

    I rebase when my delivery commit fails integration for whatever reason, and I need to update it towards a fresh remote master.

    git fetch
    git fetch <gerrit link>
    git checkout FETCH_HEAD
    git rebase origin/master
    git push origin HEAD:refs/for/master
    
    0 讨论(0)
  • 2020-11-21 12:25

    When do I use git rebase? Almost never, because it rewrites history. git merge is almost always the preferable choice, because it respects what actually happened in your project.

    0 讨论(0)
  • 2020-11-21 12:26

    While merging is definitely the easiest and most common way to integrate changes, it's not the only one: Rebase is an alternative means of integration.

    Understanding Merge a Little Better

    When Git performs a merge, it looks for three commits:

    • (1) Common ancestor commit. If you follow the history of two branches in a project, they always have at least one commit in common: at this point in time, both branches had the same content and then evolved differently.
    • (2) + (3) Endpoints of each branch. The goal of an integration is to combine the current states of two branches. Therefore, their respective latest revisions are of special interest. Combining these three commits will result in the integration we're aiming for.

    Fast-Forward or Merge Commit

    In very simple cases, one of the two branches doesn't have any new commits since the branching happened - its latest commit is still the common ancestor.

    In this case, performing the integration is dead simple: Git can just add all the commits of the other branch on top of the common ancestor commit. In Git, this simplest form of integration is called a "fast-forward" merge. Both branches then share the exact same history.

    In a lot of cases, however, both branches moved forward individually.

    To make an integration, Git will have to create a new commit that contains the differences between them - the merge commit.

    Human Commits & Merge Commits

    Normally, a commit is carefully created by a human being. It's a meaningful unit that wraps only related changes and annotates them with a comment.

    A merge commit is a bit different: instead of being created by a developer, it gets created automatically by Git. And instead of wrapping a set of related changes, its purpose is to connect two branches, just like a knot. If you want to understand a merge operation later, you need to take a look at the history of both branches and the corresponding commit graph.

    Integrating with Rebase

    Some people prefer to go without such automatic merge commits. Instead, they want the project's history to look as if it had evolved in a single, straight line. No indication remains that it had been split into multiple branches at some point.

    Let's walk through a rebase operation step by step. The scenario is the same as in the previous examples: we want to integrate the changes from branch-B into branch-A, but now by using rebase.

    We will do this in three steps

    1. git rebase branch-A // Synchronises the history with branch-A
    2. git checkout branch-A // Change the current branch to branch-A
    3. git merge branch-B // Merge/take the changes from branch-B to branch-A

    First, Git will "undo" all commits on branch-A that happened after the lines began to branch out (after the common ancestor commit). However, of course, it won't discard them: instead you can think of those commits as being "saved away temporarily".

    Next, it applies the commits from branch-B that we want to integrate. At this point, both branches look exactly the same.

    In the final step, the new commits on branch-A are now reapplied - but on a new position, on top of the integrated commits from branch-B (they are re-based).

    The result looks like development had happened in a straight line. Instead of a merge commit that contains all the combined changes, the original commit structure was preserved.

    Finally, you get a clean branch branch-A with no unwanted and auto generated commits.

    Note: Taken from the awesome post by git-tower. The disadvantages of rebase is also a good read in the same post.

    0 讨论(0)
  • 2020-11-21 12:26

    It was explained many times what rebase and what merge is, but when should you use what?

    When should you use rebase?

    Rebase "lifts off" your changes and puts all the changes of the rebased branch into your current branch and then puts your changes on top of it. It therefore changes the history of your branch.

    • when you have not pushed the branch / no one else is working on it
    • you want your to see all your changes at one point together when merging back to the source branch
    • you want to avoid the auto-generated "merged .." commit messages

    I said "you want to see all your changes at one place" because sometimes a merge operation puts all your changes together in one commit (some: merged from ... message). Rebase makes your change look like you made your commits all after each other with no one else doing something in between. This makes it easier to see, what you changed for your feature.

    Make sure though, you use git merge feature-branch --ff-only to make sure there are no conflicts creating a single commit when you are merging your feature back to develop/master.

    When should you use merge?

    • when you have pushed the branch / others are working on it too (rebase gets very complicated if others work on that branch too!)
    • you don't need the full history(*) / your feature doesn't have to have it's commits all in one place.

    (*) you can avoid that your feature only gets one "merged .." commits by first merging the develop branch to your feature and then merging your feature back to develeop. This still gives you a "merged .." commit, but a least all the commits of your feature are still visible.

    0 讨论(0)
  • 2020-11-21 12:28

    If you are only one developer you can use rebase instead of merge to have a clear history

    0 讨论(0)
提交回复
热议问题