I can’t make conclusions for myself when should I rebase ? I ask experienced comrades to share their experiences and express criteria that influence the decision about what to rebase . And also give examples of situations when it is not necessary to do it.

Let's take a situation when for implementation of feature 1 I made branch 1. At this point, the master branch is completed with commitom0. Simultaneously with me, Vasya in parallel implemented the feature2 in the branch2 and poured it into the master. Vetka2 consists of komit1, komit2, komit3 and these komit got into master. I would like to bring my branch to that state with the help of GIT, as if I had made my own branch1 starting from Comit3.

Is it permissible to use rebase in my situation?

  • five
    Describe a specific situation when you doubt whether to rebase, and what alternative it has - Abyx
  • 2
    The rebase usually means two different possibilities of rebase -i : 1) rearrange the branch to another commit (usually to the actual master ); 2) merge (squash) commits into one. What do you ask about this (or something else)? - Nick Volynkin
  • one
    I would like to separately note the point that from the point of view of the correctness of history, merge is often better than a rebey. Those. if you take the same abstract situation with the master, it is much better if the influence of your changes is marked by a separate concrete commit so that it can be tracked. - etki
  • one
    @Etki I wrote a recommendation there to use merge --no-ff after rebuy. I would be glad if you add something useful. - Nick Volynkin
  • 2
    @ixSci if the changes are local, then the team has nothing to do with it - Abyx

2 answers 2

Make a backup

Whenever in doubt, make a backup. Any way will do:

 git branch backup git tag backup git reflog 

Save the story!

If you reboot the feature branch to master before merge, I strongly recommend that you use merge --no-ff , i.e. force the creation of a merge commit. Without this, fast-forward and completely linear history will be obtained.

Merge commits will show the history of work on the project, in particular the moment of the merge feature-branch and the author of merge (who missed the code in the master). Starting with version 2.6.0, git can cancel (revert) merge commits . Without a merge commit, you will have to specify the exact set of commits for cancellation, which will not be easy with a linear history.

When it is impossible

  • You cannot rebuild anything in stable branches ( master , stable , production , release-1.0 , etc.).
  • When you started a commit to a remote repository (shared) and someone used it:
    • Branched off from him
    • Made a cherry-pick to another branch
    • I went to another branch
    • Linked to this commit (GitLab & GitHub in this case create a comment on the commit page with reference to the link)
  • You can never rebuild someone else's commits. If you do this, Linus will come to you at night and make a hand re-draw on your hips .

Carefully

When you rebuy a branch from more than one commit and performance is important to you in intermediate commits, check each post rebuy. Rebeyz rewrites the contents of each intermediate commit, so if you have previously compiled a specific commit code or passed the tests, it’s not a fact that it will pass after the rebuy.

If there are a lot of commits in your branch and there are conflicts, you will have to resolve them many times (precisely because the contents of each commit are being rewritten). For comparison, with the usual merge, you resolve them once, in merge commit itself.

When can

  • When you have a local branch that is not in the remote repository
  • Or when there is a branch in the remote repository, but no one has used it exactly.

When should

  • If in your team it is customary to rebuy to master before merge and / or the opening of merge-requisition.
  • If your team decided to merge (flatten, squash) commits into one before merge and / or the opening of merge-request.

The above reasons work if there is also a rule in the team not to use other people's commits that are not locked to the master. If any of the conditions from the section “When it is impossible” is fulfilled - it is impossible to re-raise

Testing before merge

Rebeyz gives some advantage in testing. Suppose there are master and feature branches. Automatic and manual tests, auto code checks, profilers, etc. show a positive result on both branches. Will this result remain after merge? In general, it is unknown. Even if it is merg without conflicts, the code may not compile at all after merge.

Therefore, there is a reason to rebuild master before final testing. Then the head commit feature will be identical to the future merge commit. But this method is ineffective for the reasons already described:

  1. Requires extra work on conflict resolution
  2. Breaks the contents of intermediate commits

If there is a need to resolve conflicts and conduct a full test of the result of merge, but so far not merge in master, it is better to apply the reverse merge technique: master merzhitsya in feature . Accordingly, merge commit appears in the feature branch.

The resulting merge commit can be tested locally, it can be launched into a remote origin/feature branch to update the merge request, run tests, CI, deploy to a test environment, etc. When all checks are passed, make a "direct" merge - feature in the master .

You do not need to merge master into your branch just in the process of working on features, this leads to a story in the form of a Moscow metro map. If you can do without master merge in feature - be sure to get along.

  • Correctly, I understood from the answer that if the team does not use these rebase, then they are not needed at all? I just do the merge wizard before pullRequest, resolve conflicts and that's it. And why this rebase is not clear) - YuriySPb
  • @Yuriy SPb merzh masters slightly complicates the graph of history. If nobody has used your commits, you can squash all the commits into one + re-create to master. Then it is necessary to resolve conflicts only once, as with Merzh. In the history there will be only one laconic commit and merge-commit in the master. - Nick Volynkin
  • @YuriSPb but it is not suitable for an intermediate review, for example. - Nick Volynkin
  • “You can't rebuild anything in stable branches” can and should be - git pull --rebase - ixSci
  • @NickVolynkin, You just described so many scary things ... Now it will be scary for me to do it) - YuriySPb

In this situation, the graph looks like this:

 > git log --graph --decorate --oneline --all * 12ef823 (HEAD -> master) Merge branch 'b2' |\ | * 3b8d7a6 (b2) b2:commit3 | * 5892389 b2:commit2 | * 245fefe b2:commit1 |/ | * ccca93c (b1) b1:commit1 |/ * 406f362 initial commit 

rebase

The easiest and most logical way to upgrade is to rebase

 > git checkout b1 > git rebase master > git log --graph --decorate --oneline --all * 5f613a9 (HEAD -> b1) b1:commit1 * 12ef823 (master) Merge branch 'b2' |\ | * 3b8d7a6 (b2) b2:commit3 | * 5892389 b2:commit2 | * 245fefe b2:commit1 |/ * 406f362 initial commit 

merge

In principle, you can keep yourself a master, but at the same time the graph becomes more complicated

 > git checkout b1 > git merge master > git log --graph --decorate --oneline --all * 16d4e98 (HEAD -> b1) Merge branch 'master' into b1 |\ | * 12ef823 (master) Merge branch 'b2' | |\ | | * 3b8d7a6 (b2) b2:commit3 | | * 5892389 b2:commit2 | | * 245fefe b2:commit1 | |/ * | ccca93c b1:commit1 |/ * 406f362 initial commit 

And after merge to master graph will be even more difficult:

 > git checkout master > git merge b1 --no-ff > git log --graph --decorate --oneline --all * 1443680 (HEAD -> master) Merge branch 'b1' |\ | * 16d4e98 (b1) Merge branch 'master' into b1 | |\ | |/ |/| * | 12ef823 Merge branch 'b2' |\ \ | * | 3b8d7a6 (b2) b2:commit3 | * | 5892389 b2:commit2 | * | 245fefe b2:commit1 |/ / | * ccca93c b1:commit1 |/ * 406f362 initial commit 

new branch

Instead of rebase, you can make a new branch, and move your commits there.

 > git checkout -b b1-1 master > git cherry-pick ccca93c > git log --graph --decorate --oneline --all * ebaac4a (HEAD -> b1-1) b1:commit1 * 12ef823 (master) Merge branch 'b2' |\ | * 3b8d7a6 (b2) b2:commit3 | * 5892389 b2:commit2 | * 245fefe b2:commit1 |/ | * ccca93c (b1) b1:commit1 |/ * 406f362 initial commit 

but it makes little sense

  • можно вмержить себе мастер - I am against the imprisonment of the master, unless it is strictly necessary. - Nick Volynkin
  • @NickVolynkin I also do not see the point (even if push -f disabled), but this does not negate this possibility - Abyx
  • Well, you have shown well what kind of hell it leads to. ) - Nick Volynkin