简体   繁体   中英

Should I use git rebase instead of git merge when I am the only working on the two concerned branches

Say the rebase involves two branches A and B . I am the only one making changes to those branches but there are other people who have pulled those branches just to view what's going on (reviewing). They have not made / will not make any changes to those branches at all. Considering the pros/cons of rebase vs merge, rebasing is clearly the better option for

Now, The git document on rebase mentions the golden rule about rebasing

The golden rule of git rebase is to never use it on public branches.

and explains why it can be dangerous.

I understand the differences between rebase and merge and how things can go wrong in situations when there are other developers committing to the parent branch.

Should I avoid this even when I am the only developer to those two branches concerned with rebasing ? What are the things that could go wrong after I force push after rebasing and the other team members try to pull those branches (again just to view them, they haven't made any changes)?

To determine whether to use rebase or merge, you first need to understand how they work.

In git commits are chain of linked list with latter commit having reference to previous commit.

C1<-C2<-C3<-C4

When two branches merge a new merge commit is created (represented below by M1)

C1<-C2<-C3
 \        \
  \       M1
   \      /
   C4<-C5

which has reference for commits which are merging. Here history is no more a linked list . It has become a directed acyclic graph.

Rebase works in a bit different way

C1<-C2<-C3 branch1
  \  
       C4<-C5 branch2

#On branch2
git rebase branch1

  C1<-C2<-C3<-C4'<-C5'

Rebase has created two new commits C4' and C5' instead of C4 and C5 and moved branch pointer to C5'. Here history is clean linked list (as your branch commits are recreated and applied over to branch with which rebase is done), but two new commits are created, means history changed for branch2 (earlier which was C1<-C4<-C5). So you have to do force push every time you do a rebase.

Now to answer your question:

  1. Should I avoid this even when I am the only developer to those two branches concerned with rebasing? In best practice it is always good to rebase your feature branch with parent branch and then merge your feature branch into parent branch , as feature branch is your own branch but parent branch will have other developers commits as well, which can get lost if you rebase your parent branch with feature branch without taking pull from remote.

  2. What are the things that could go wrong after I force push after rebasing and the other team members try to pull those brances? It will go pretty bad as force push, push whatever history you have on your local system to remote . If you don't use force push then your push will get rejected incase of mismatched history and commit transition and you will be asked to take the pull. Also if you have force pushed on parent branch which had some other developers commit and same was not pulled on your local machine, then that commit is lost.

If other developer tries to pull from remote, he will get a tree conflict as his local history will not mach with remote.

A problem could arise when the reviewers pull your code.

Git will fetch the rebased commits and try to merge it with reviewer's branch.

This will either create a merge commit - if everything goes well or it will lead to a merge conflict.

Because git has no way of knowing if the new commits are rebased or completely different, it will keep old pre-rebase commits and merge it with post-rebase commits. In either case, the commit history on their machines will always be different from yours even if the code is the same.

There is an expanded version of your "golden rule" on rebasing:

The golden rule of git rebase is to never use it on public branches.

The expanded version goes like this: Only use rebase, or other force-push type motions, on branch names where all users of that name expect the behavior that results . This is because each such user may have to take some action to recover from such an operation (an "upstream rebase"): namely, he or she may have to "rescue" his or her commits. If all users are prepared to do so, and know to look for such cases, they won't be surprised by the problem.

In other words, if you have a team of, say, five programmers, and all five of you agree that the "pu" ("proposed update" or "pickup" branch) gets rebased all the time, it's fine to rebase the pu branch. If one of you is OK with rebasing "develop" but four are not , it's not OK to rebase the "develop" branch.

Since you are the sole user and developer working with A and B, it's up to you to decide whether you agree with yourself as to whether it is OK to rebase A and/or B.

What are the things that could go wrong after I force push after rebasing and the other team members try to pull those branches (again just to view them, they haven't made any changes)?

Nothing can really go "wrong". The worst thing that can happen is that the "viewers" will have unnecessary trouble with merging since your newly force-pushed commits may look completely different and now pulling (ie fetching and merging) them results in merge conflicts .

Should I avoid this even when I am the only developer to those two branches concerned with rebasing?

While rebasing allows you to have a tidy and linear git history and definitely has its benefits, here are some thoughts on why "merging" sometimes could be preferable over "rebasing", even though you are in "write"-control over your branches:

1) To avoid irreversible code deletions resulting from wrong decisions during merge conflicts.

Example: Say you have been working on your feature branch A for two weeks and now you stop working on it and instead continue on branch B for two weeks. Now after some time you feel it is time to work on branch A again and for some reason you need changes contained in B incorporated into A so you decide to rebase your branch A onto B . In the course of this rebase several merge conflicts arise. Due to poor judgement or by mere accident, you remove parts of your code in A to solve the conflics in favour of the incoming changes. Now you continue and complete your rebase and force push your code to your remote's origin/A . Suddenly you realize that you deleted parts of your code in branch A that were important and shouldn't have been deleted. However, since rebase rewrites history, unlike a merge, you cannot simply revert the rebase and your code is lost.

The situation described above is especially problematic if you tell juniors in your team to always prefer rebase over merge and they accidentally delete their code by making wrong decisions in the course of merge-conflicts, especially when rebasing their branch onto the master .

Of course a solution to this problem apart from using git merge would be to make a backup branch before performing a rebase.

2) To avoid solving too many conflicts while interactively rebasing.

When your feature branch contains several commits, ie you moved code around quite a bit and maybe even back and forth, then rebasing may take much longer than a merge, because a rebase will go in sequence (!) through your branch's commits one by one and stops at every conflict that is discovered. With a merge, you will only compare the current state, ie the HEAD , of your feature branch with the HEAD of the branch you are rebasing onto (eg the master ) and it might be that there are no conflicts at all when performing a merge while there could be some conflicts when doing a rebase. So in this sense, a merge potentially saves you some time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM