What does git Graph readable mean?
By being readable, I mean being able to look at git Graph and see the record of every release change and every hotfix change. To reflect on a branch, there are two requirements:
- Historical changes for each branch are readable (individual branch level)
- Fork merge for each branch readable (level of multiple branches)
What is rebase, and is it a more elegant merge?
Rebase translation makes a change (re) base (base).
Articles on Rebase often cite three diagrams:
Git merge git rebase git merge Git merge git merge The purpose of Rabase is not to merge branches, it is not at all the same as merge.
Rebase also has several uses:
The git pull - rebase
Resolving conflicts on the same branch (if you understand what this isgit fetch&&git rebase
Two operations, with an understanding of the difference between remote and local branches, are no different from pure rebase usage, but the scenario is different, so it is broken out separately.)git rebase -i
Modifying a Commit Record
In essence:
- A merge is a merger of two branches of a current fork
- Rebase is right
The current branch
Records are based on anyCommit node
(not limited to nodes on the current branch).
The base of a rebase cannot be understood as the base of a fork, but as all commit nodes that exist in the entire Git repository:
- in
The git pull - rebase
When thisThe current branch
It’s a local branch,Commit node
Is the head of the remote branch - in
git rebase master
When thisThe current branch
Is the feature branch,commit
The node is the head of the master branch - in
git rebase -i
When thisThe current branch
Is the current work branch,Commit node
Commit is written after -i
How does Rebase work?
We’ve already said this:
Rebase is a change to the current branch record based on any COMMIT node (not limited to nodes on the current branch).
How do you do that? I haven’t delved into how it really works, and the steps below are definitely wrong, but enough to give you an idea of what Rebase does.
We highlight two key points, the current branch and the COMMIT node.
- the
The current branch
Branch-a is listed from beginning to end, which is A linked list from A data structure perspective - the
Commit node
Branch branch-b is listed from beginning to end, again as a linked list - Find the most recent node n that is the same between the two lists
- All nodes of A after n are removed to form L
- D is formed by summarizing the diff information of B in all nodes after N
- For each node in L, pull out its diff information and see if there is any conflict in D. If there is any conflict that cannot be handled automatically, throw an error and wait for the user to handle it
- Optionally, for
rebase -i
You can also take multiple nodes at once or take them in a different order, so you have more freedom - Change a hash to branch-b for nodes that have no conflicts and nodes that have finished processing conflicts
Commit node
Then you can apply the three rebase uses we talked about earlier to the above steps and see if it makes sense.
Rebase is dangerous, right?
Yeah, it’s dangerous.
But like a pony crossing a river, it is no use just listening to what others say. We need to understand why some say it is dangerous and others say it is not. I’ve read a lot of articles about what’s wrong with Rebase, but they’re not really convincing, and a lot of times they just don’t use it.
Many people have heard of a golden Rule, linked to at the end of this article, but few will understand the real reason. Let’s break it down layer by layer:
- Other git pushes compare local and remote branches and push different places up
- If the remote branch is changed, then someone else’s local branch and remote branch will fork (and possibly overwrite the work that someone else has already pushed).
- When a fork occurs, it means that someone else has to deal with the conflict, that is, your changes to the remote history make
The conflict spilled over into others
- So we try not to modify the remote branch, no
Fetch others back to change
, because their work is based on the fetch back branch (it is necessary to move forward, but also modify the remote branch, so the merge will cause a conflict, but this conflict is unavoidable) - If you violate the above rule,git will block a push, but by adding one
-f
Can strong push
In fact, it’s not just Rebase; any attempt to modify the history of a remote branch creates a conflict that needs to be resolved by everyone.
But the analysis is still too long to remember what to do?
Just remember -f, as long as you don’t use -f, then it’s safe.
However, security alone does not guarantee elegance. If you want to make Git Graph readable, you need to think a little bit more:
- How to make your commit history clear (each commit reflects one unit of work, in a reasonable order)
- How to make every hotfix and feature work and order clear
How does Rebase make Git Graph readable?
Let’s go back to the three uses we mentioned earlier:
git rebase master
Use git rebase master instead of git merge master when merging branches back to master.
The benefits are twofold:
- There won’t be one in the log
Merge branch 'master' into hotfix/xxx
The nodes of the - That has been committed on the Master branch before this merge
Last Job
And the work sequence of this time is clearer, because rebase will change the bifurcation node of this feature to the one after the last work. For the master branch, we don’t care about the order of the new checkout featureMerge the order of new features
.
For example, in this case, the purple fork that was merged with the master was joined one more time before the commit, and there was also a merge on the main line before the purple fork merged. The time sequence is not clear.
Does merging on the master branch also use Rebase? No, because we need forks on the master to make us more aware of the changes on the master (so we use -no-ff). In fact, regardless of your Git flow model, I recommend rebase for less important branch merges and merge for important branch merges. This will make changes to the trunk clearer and the branches will not spread out too far.
The git pull – rebase
Git merge Merge is the default behavior of git pull, and the merge object is the remote branch and the local branch.
It has basically the same benefits as the previous one, plus one:
- Pull using the merge behavior produces a new fork in the graph by treating other people’s work as an external fork, And all of the work done by other people during that period of time will be lifted out of the graph, and if other people are doing a lot of work during that period of time, the graph’s main thread will lose its meaning (because it is so thin that a lot of work will not be reflected at all).
For example, in this case, the main line is the second magenta color from the left, but it was raised to the outer layer because of the merge pull. This time the non-standard COMMIT became the main line.
git rebase -i
This command can be used to modify the branch records. For example, if you feel that the previous commit changes are not unitary, such as modifying copywriting 1 to copywriting 2 and copywriting 2 to copywriting 3, such records are unnecessary information for the master branch. It is better to use Git commit Amend or rebase.
However, manually squashing the entire branch before committing is not recommended; rebase merging may make more sense. Gongfu (Tencent’s internal code platform) provides the title and content functions of Merge Request, so there is no need to squash. You can completely avoid aggregation to reflect real information.
In order not to affect others, use it only to change the commit that is not pushed, or if there is only one person on a branch, you can also change the commit that has been pushed.
For more on this command, check out other articles.
What should a readable graph look like?
First of all, let’s talk about a principle. When looking at graph, we should first look at the main line, which should be clear, and then look at the information on the fork. This is consistent with our work flow.
The green hotfix or feature branch does not allow only one commit at a time, but only a few small changes.
It seems ridiculous. It’s not high class. Did all this talk and all this work just to get such a simple picture?
Yes, in order to make things simple, we have to pay a lot of costs, what we do is to make things simple, such as working hard in order to make money easy, working hard in order to make work easy. Making things complicated only makes things out of control.
It depends on what git flow you use, but the principle is simple:
The sub-forks of each fork should be a series one as far as possible, and there should be no more internal commits of its own.
The reason why I think git Graph is so readable is because it flatters our work, not caring about the start time and duration of each work, but the completion time of the work.
Let’s say a project requirement 1 is launched on January 1st and launched on February 1st, requirement 2 is launched on January 20th and launched on February 10th. A bug was fixed on January 10th and a bug was fixed on February 3rd. Does that sound convoluted?
If your Git graph displays this kind of information, it will not be very readable, so our git graph should reflect the following information:
- Fixed the bug on January 10
- Demand 1 will be online on February 1st
- Fixed the bug on February 3rd
- Demand 2 will be online on February 10th
What are the downsides of Rebase?
(I’m not going to discuss rebase’s potential conflicts here, there are many articles that do, and the dangers of Rebase have already been mentioned, but I’m going to discuss the drawbacks of Rebase for git Graph. In fact, conflicts are a problem caused by improper use of Rebase, not rebase itself.
Of course, some people would say that the start time of the work is also very important, because it reflects the basic conditions of the work at that time. Yeah, that’s the downside of rebase Master. He makes the record clear, and he makes the record lose some information. The processing of records leads to better readability and less information.
Git rebase changes the Git graph so that there are no nodes between checking out and merging each fork (because merging to master takes the merge behavior). Otherwise there are no forks at all.)
That’s not going to happen again. Git rebase actually makes the check out information meaningless in exchange for clarity on the master branch.
If Rebase had no drawbacks, there would be no controversy. Whether or not to use Rebase also depends on what the real requirements are.
What is the purpose of this article?
Make git Graph more readable with rebase. We have already said the objectives and principles, there is no need to restate them.
There are many fallacies, but also hope to give advice!