Learn git rebase. Just read this one

preface

Hello, everyone, unknowingly, the eight day long holiday is coming to an end. After playing for so many days, I have to close my heart and start learning today. I'm going to work tomorrow. Today, my sister suddenly asked me what the GIT rebase instruction is for and how to use it? In fact, I don't want to tell him, but I still haven't escaped my sister's soft grind and hard bubble, so let's take a look at what git rebase is!!!

origin

In other words, the fate between me and my sister was on that dark and windy night. PA, my sister slapped me in the face and said: can you talk about the key points. Ha ha, no kidding, just get to the point. Let's take a look at a scenario first. I checked my personal warehouse on github. There are many commit submissions. The submission contents are as follows:

With so many submissions, many have no standardized names. It's really bad to open them casually because they are used by themselves. In fact, some unnecessary submissions can be merged together, which will lead to the following problems:

  • This causes branch pollution. The project is full of many commit records. When there is an urgent problem and the code needs to be rolled back, you can only view it one by one.
  • Code review is inconvenient. When you want to do code review, a small function has been submitted many times, which seems not very convenient.

In this article, we won't talk about git submission specification first. Let's solve how to merge multiple submission records first.

rebase: submit record

Through the above scenario, we can extend the first function of GIT rebase: merging and submitting records. Now we want to merge the last 5 submission records and execute:

$ git rebase -i HEAD~2

vim editing mode will pop up automatically after executing the instruction:

pick e2c71c6 update readme
pick 3d2c660 wip: merge`

# Rebase 5f47a82..3d2c660 onto 5f47a82 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

From here, we can see that the first five lines are the records we want to merge, but they all have the same instruction: pick, what instruction is this? Don't panic. No, the following commands have been given:

pick: Keep the commit(abbreviation:p)

reword: Keep the commit´╝îBut I need to change that commit Notes (abbreviations) for:r)

edit: Keep the commit, But I'm going to stop and modify the submission(Not just modify comments)(abbreviation:e)

squash: Will this commit And the previous one commit Merge (abbreviation):s)

fixup: Will this commit And the previous one commit Merge, but I don't want to keep the comment information (abbreviation) of the submission:f)

exec: implement shell Command (abbreviation):x)

drop: I want to discard the commit(abbreviation:d)

label: Mark current with name HEAD(abbreviation:l)

reset: take HEAD Reset to label(abbreviation:t)

merge: Create a merge branch and use the original branch commit Notes for(abbreviation:m)

According to these instructions, we can make modifications as follows:

pick e2c71c6 update readme
s 3d2c660 wip: merge`

After modification, click Save to exit and enter the comment interface:

# This is a combination of 2 commits.
# This is the 1st commit message:

update readme

# This is the commit message #2:

wip: merge`

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Thu Sep 17 22:03:52 2020 +0800
#
# interactive rebase in progress; onto 5f47a82
# Last commands done (2 commands done):
#    pick e2c71c6 update readme
#    squash 3d2c660 wip: merge`
# No commands remaining.
# You are currently rebasing branch 'master' on '5f47a82'.
#
# Changes to be committed:
#       new file:   hash/.idea/.gitignore
#       new file:   hash/.idea/hash.iml
#       new file:   hash/.idea/misc.xml
#       new file:   hash/.idea/modules.xml
#       new file:   hash/.idea/vcs.xml
#       new file:   hash/go.mod
#       new file:   hash/hash/main.go
#       modified:   snowFlake/Readme.md

The meassage of each submission is listed above. Because we want to merge the two commit ments, the submission comments can be modified into one, and the final editing is as follows:

# This is a combination of 2 commits.
# This is the 1st commit message:

fix: merge update and wip: merge`

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Thu Sep 17 22:03:52 2020 +0800
#
# interactive rebase in progress; onto 5f47a82
# Last commands done (2 commands done):
#    pick e2c71c6 update readme
#    squash 3d2c660 wip: merge`
# No commands remaining.
# You are currently rebasing branch 'master' on '5f47a82'.
#
# Changes to be committed:
#       new file:   hash/.idea/.gitignore
#       new file:   hash/.idea/hash.iml
#       new file:   hash/.idea/misc.xml
#       new file:   hash/.idea/modules.xml
#       new file:   hash/.idea/vcs.xml
#       new file:   hash/go.mod
#       new file:   hash/hash/main.go
#       modified:   snowFlake/Readme.md

After editing, save and exit. This completes a merge commit. Let's verify:

$ git log
15ace34 (HEAD -> master) fix: merge update and wip: merge`
5f47a82 update snowFlake code

From here, we can see that two submissions become one, reducing useless submission information.

Role 2: Branch merger

We seldom use this scenario together, but we still need to know its function.

Suppose we have a new project. Now we want to cut out a dev branch from the master branch for development:

$ git checkout -b dev

At this time, your colleague completes a hotfix and merges into the master branch. At this time, the master is already ahead of your dev branch:

After the repair, the colleague notifies you in the group that it is exactly the part you need, so now we need to synchronize the changes of the master branch and merge with merge:

$ git merge master

The green dot in the figure is the result of our merging. If we execute git log, we will find some merge information in the record, but we think this pollutes the commit record. What should we do if we want to keep a clean commit? At this time, git rebase comes in handy.

So now let's try using git rebase. Let's go back to hotfix and merge the master. Now I don't use merge to merge, but use the rebase instruction directly

$ git rebase master

At this time, git will cancel each commit in the dev branch, and then temporarily save the above operation as a patch file and save it git/rebase directory; Then, update the dev branch to the latest master branch; Finally, apply the patch file saved above to the dev branch;

From the commit record, we can see that the dev branch is based on the master after hotfix merger. It naturally becomes the leading branch, and it doesn't have the commit record of merge. Does it feel very comfortable.

When we use rebase to merge branches, conflict will also appear. In this case, GIT will stop rebase and let you solve the conflict. After resolving the conflict, use the git add command to update these contents. Then execute git rebase --continue again, so that git will continue to apply the remaining patch files.

If we don't want to perform this rebase operation now, we can return to the pre start state through -- abort:

git rebase --abort

rebase is a dangerous operation - use with caution

It seems that rebase operation is perfect, but it is also dangerous. Let's take a look at it together.

Now let's assume that after we develop in the dev branch and perform the rebase operation, before submitting the code to the remote, it is as follows:

After submitting the dev branch to the remote code warehouse, it becomes like this:

At this time, your colleague is also developing on dev, and his branch is still the former dev, and there is no synchronization master:

Then when he pull s the remote master, he will lose the submission record. This is why we often hear people say that git rebase is a dangerous command, because it has changed history, and we should use it carefully.

However, if all the commit history of rebase on your branch has not been push ed, you can safely use git rebase to operate.

summary

Under the careful explanation of asong, my sister completely understood how to use git rebase. Let's take a look at my sister's summary:

  • When we develop on an outdated branch, we execute rebase to synchronize the latest changes of the master branch;
  • If we want to start a parallel work that has been placed for a long time, and now we have time to continue it, it is obvious that this branch has fallen behind. At this time, you need to start working on the latest benchmark, so rebase is the most appropriate choice.
  • Git rebase is perfect and solves our two problems:

    • Merge the commit records and keep the branches clean and tidy;
    • Compared with merge, it will reduce the records of branch merging;
  • One thing to pay attention to when using rebase operation is that if all the commit history of rebase required on your branch has not been push ed, you can safely use git rebase to operate.

It seems that you have learned it. What about your sister?

It doesn't matter if you try it yourself.

Well, that's the end of this article. I'll see you next time.

At the end, I'll give you a little benefit. Recently, I've been reading the book "microservice architecture design pattern", which is very good. I also collected a PDF, which can be downloaded by those in need. Access method: follow the official account: [Golang DreamWorks], and the background reply: [microservice].

I translated a gin Chinese document, which will be maintained regularly. If you need it, you can download it by replying to [gin] in the background.

I'm asong, an ordinary program ape. Let me grow stronger together. I set up a golang exchange group myself. If you need a partner, add me vx, and I'll pull you into the group. Welcome your attention. I'll see you next time~~~

Recommended previous articles:

Tags: Go git

Posted by lucasrd on Fri, 13 May 2022 06:40:13 +0300