📜 ⬆️ ⬇️

The golden rule of git rebase

Hello!

We rewrote our web development course here a bit and added another month of studying JS. Well, as usual with us - consider something interesting that understands our course. In this case, git rebase.

Go.
')
What actually happens during git rebase, and why should you care.

Basics of rebase

So you could imagine a rebase in git:



You might think that when you rebase, you “detach” the branch you want to relocate and “attach” it to the end of another branch. This is not very far from the truth, but it is worth digging a little deeper. Here is what the rebase documentation says:

“Git-rebase: Forward-port local commits to the updated upstream head” - git documentation

Not very helpful, is it? Approximate translation (and translation of translation) may be as follows:

git-rebase: Reapply all commits from your branch to the end of another branch.

The most important word here is “reapply”, because rebase is not just ctrl-x / ctrl-v from one branch to another. Rebase will consistently take all commits from the branch you are in and reapply them to another branch. This has two important consequences:

  1. Replacing commits, git creates new ones. These new commits, even if they make the same set of changes, will be viewed by git as completely different and independent.
  2. Git rebase reapplies commits without destroying old ones. This means that even after rebase, the old commits will still be in the / objects folder in your .git directory. If you're still unfamiliar with how git views and stores commits, you can find out something interesting here.

Thus, this may be a more accurate idea of ​​what actually happens during a rebase:



As you can see, the feature branch has completely new commits. As already mentioned, it has the same set of changes, but completely different objects in terms of git. And you can also see that the previous commits are not destroyed. They are simply not available directly. If you remember, a branch is only a pointer to commits. Therefore, if neither branches nor tags point to commits, it becomes almost impossible to get them, but commits still exist.

Now let's talk about the famous golden rule.

The golden rule of rebase

"Do not rebase the common branch" - Everything and everyone about rebase

You have probably already come across this rule, perhaps formulated differently. For those who did not, this rule is quite simple. Never, NEVER, NEVER rebase a common branch. By a common branch, I mean a branch that exists in a remote repository and which other people from your team can bully themselves.

Too often, this rule is presented as a divine truth, and I think you should figure it out if you want to improve your understanding of git.

To do this, let's imagine a situation where a developer violates this rule, and see what happens.

Let's say Bob and Anna are working on the same project. Here is the Bob, Anna repository, and remote repository on GitHub:



Everything is synchronized with a remote repository (GitHub)

Now Bob innocently violates the golden rule of rebase, at the same time Anna decides to work on this feature and creates a new commit:



Guess what will happen?

Bob tries to push, he gets a failure and sees the following message:


Oh my zsh with agnoster theme for those who are interested.

Git is not happy, because it doesn’t know how to merge the feature branch of Bob with the feature branch of GitHub. Usually, when you push your branch to a remote repository, git merges the branch that you are trying to push with the branch located in the remote repository. To be precise, git is trying to fast-forward your branch, and we will talk about this in a future post. What you need to remember is that the remote repository cannot, in a simple way, deal with the relocated branch that Bob is trying to push.

One solution for Bob would be to make git push-force, which tells the remote repository:
“I’m pushing what you’ve already been. I’m pushing now for the new feature branch
And this is what we end up with:
“Do not try to combine or do any other work between what I push and what you already have. Erase my version of the feature branch: what I am pushing is now a new feature branch ”

And this is what we get:



If Anna knew what was going to happen, she would not have gone to work this morning.

Now Anna wants to push her changes:



This is normal, git simply told Anna that she does not have a synchronized version of the feature branch, i.e. its version of the branch and the version of the GitHub branch are different. Naturally, Anna bullet. Just as git tries to merge your local branch with what is in the remote repository when pushing, git tries to merge what is in the remote repository with what is in your local branch when you pull.

This is how commits look in the remote and local feature in front of the pool:

A--B--C--D' origin/feature // GitHub A--B--D--E feature // Anna 


When you pull, git must do a merge to solve this problem. And that's what happens:



Commit M is a merge commit — a commit in which Anna's branch and GitHub are finally reunited. Anna finally sighs with relief, she managed to resolve all the merger conflicts, and now she can push her work. Bob decides to run, and now everything is synchronized.



One glance at this mess should be enough to convince you of the fairness of the golden rule. You should keep in mind that you are in front of a mess created by only one person, in a branch shared by only two people. Imagine doing this with a team of 10 people. One of the many reasons why people use git is that you can easily “go back in time”, but the more messy your story is, the harder it gets.

You may also notice duplicate commits in the repository - D and D ', which have the same set of changes. The number of duplicated commits can be as large as the number of commits within your relocated branch.

If you're still not sure, try to introduce Emma, ​​the third developer. She worked on the feature before Bob ruined everything, and now she wants to push changes. Please note that she fushes after our previous mini-script.


damn it bob!

update: As one reddit user noted, this post might make you think that rebase can only be used to relocate a branch to the top of another branch. This is not the case; you can relocate the same branch, but that’s another story.

Thanks for attention.

THE END

As always, we are waiting for your questions, comments here or you can torment the teachers in an open lesson.

Source: https://habr.com/ru/post/352640/


All Articles