The branch is the parallel universe in science fiction movies. When you are trying to learn Git in front of the computer, another you are trying to learn SVN in another parallel universe.
If two parallel universes don't interfere with each other, it won't affect you now. However, at a certain point in time, two parallel universes merge. As a result, you learn both Git and SVN!
What is the use of branching in practice? Suppose you are going to develop a new function, but it takes two weeks to complete it. In the first week, you wrote 50% of the code. If you submit it immediately, because the code has not been written, the incomplete code base will make others unable to work. If the code is written and submitted again, there is a huge risk of losing the daily progress.
Now that you have branches, you don't have to be afraid. You create a branch that belongs to you, but others can't see it and continue to work normally on the original branch. You work on your own branch and submit it if you want. After the development is completed, you can merge it into the original branch at one time. In this way, it is safe and does not affect the work of others.
Other version control systems, such as SVN, have branch management, but after using it, you will find that these version control systems create and switch branches more slowly than snails, which is unbearable. As a result, the branch function has become a decoration and everyone doesn't use it.
But Git's branches are different. Whether creating, switching or deleting branches, Git can complete them in 1 second! Whether your version library is 1 file or 10000 files.
Create and merge branches
We know that Git strings them into a timeline every time it submits, and this timeline is a branch. So far, there is only one timeline. In Git, this branch is called the main branch, that is, the master branch. Strictly speaking, HEAD does not point to submission, but to master, which points to submission. Therefore, HEAD points to the current branch.
At the beginning, the master branch is a line. Git uses master to point to the latest submission and HEAD to point to master to determine the current branch and the submission point of the current branch:
Each time you submit, the master branch will move forward one step. In this way, as you submit, the line of the master branch will become longer and longer.
When we create a new branch, such as dev, Git creates a new pointer called dev, which points to the same commit as the master, and then points the HEAD to dev, indicating that the current branch is on dev:
You see, Git creates a branch very quickly, because in addition to adding a dev pointer and changing the direction of HEAD, there is no change in the files in the workspace!
However, from now on, the modification and submission of the workspace are aimed at the dev branch. For example, after a new submission, the dev pointer moves forward one step, while the master pointer remains unchanged:
If our work on dev is completed, we can merge dev into the master. How does Git merge? The simplest way is to directly point the master to the current commit of dev to complete the merge:
So Git merges branches very quickly! Just change the pointer and the content of the workspace will remain the same!
After merging the branches, you can even delete the dev branch. Deleting the dev branch is to delete the dev pointer. After deletion, we have a master branch left:
It's amazing. Can you see that some submissions are done through branches?
Let's start the actual combat.
First, we create the dev branch, and then switch to the dev branch:
$ git checkout -b dev Switched to a new branch 'dev'
The git checkout command plus the - b parameter indicates creation and switching, which is equivalent to the following two commands:
$ git branch dev $ git checkout dev Switched to branch 'dev'
Then, use the git branch command to view the current branch:
$ git branch * dev master
The git branch command will list all branches, and the current branch will be preceded by a * sign.
Then, we can commit normally on the dev branch, such as readme Txt make a change and add a line:
Creating a new branch is quick.
Then submit:
$ git add readme.txt $ git commit -m "branch test" [dev b17d20e] branch test 1 file changed, 1 insertion(+)
Now that the dev branch is completed, we can switch back to the master branch:
$ git checkout master Switched to branch 'master'
After switching back to the master branch, view a readme Txt file, the content just added is missing! Because the commit is on the dev branch, and the commit point of the master branch has not changed at the moment:
Now, let's merge the work of dev branch into master branch:
$ git merge dev Updating d46f35e..b17d20e Fast-forward readme.txt | 1 + 1 file changed, 1 insertion(+)
The git merge command is used to merge the specified branch to the current branch. After merging, view readme Txt, you can see that it is exactly the same as the latest submission of the dev branch.
Noting the fast forward information above, Git told us that the merge is in the "fast forward mode", that is, direct the master to the current commit of dev, so the merge speed is very fast.
Of course, not every merge can be fast forward. We will talk about other merging methods later.
After merging, you can safely delete the dev branch:
$ git branch -d dev Deleted branch dev (was b17d20e).
After deletion, check the branch, and only the master branch is left:
$ git branch * master
Because creating, merging and deleting branches are very fast, Git encourages you to use branches to complete a task and delete branches after merging. This has the same effect as working directly on the master branch, but the process is safer.
Summary
Git encourages extensive use of branches:
-
View branch: git branch
-
Create + switch branch: git checkout - B < name >
-
Merge a branch to the current branch: git merge < name >
-
Delete branch: git branch - d < name >
Conflict resolution
Nine times out of ten, merging branches is not always easy.
Prepare a new feature1 branch and continue our new branch development:
$ git checkout -b feature1 Switched to a new branch 'feature1'
Modify readme Txt last line, change to:
Creating a new branch is quick AND simple.
Submit on feature1 branch:
$ git add readme.txt $ git commit -m "AND simple" [feature1 14096d0] AND simple 1 file changed, 1 insertion(+), 1 deletion(-)
Switch to the master branch:
$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits)
Git will also automatically prompt us that the current master branch is 1 commit ahead of the remote master branch.
On the master branch, put readme The last line of the txt file is changed to:
Creating a new branch is quick & simple.
Submission:
$ git add readme.txt $ git commit -m "& simple" [master 5dc6824] & simple 1 file changed, 1 insertion(+), 1 deletion(-)
Now, both the master branch and the feature1 branch have new submissions respectively, which becomes as follows:
In this case, Git cannot perform "quick merge" and can only try to merge their changes, but this kind of merge may have conflicts. Let's try:
$ git merge feature1 Auto-merging readme.txt CONFLICT (content): Merge conflict in readme.txt Automatic merge failed; fix conflicts and then commit the result.
Sure enough, there was a conflict! Git told us that readme Txt file has conflicts, which must be manually resolved before submission. git status can also tell us the conflicting files:
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a")
We can check readme directly Txt contents:
Git is a distributed version control system. Git is free software distributed under the GPL. Git has a mutable index called stage. Git tracks changes of files. <<<<<<< HEAD Creating a new branch is quick & simple. ======= Creating a new branch is quick AND simple. >>>>>>> feature1
Git marks the contents of different branches with < < < < <, =========, > > > > > > >. We modify them as follows and save them:
Creating a new branch is quick and simple.
Resubmission:
$ git add readme.txt $ git commit -m "conflict fixed" [master cf810e4] conflict fixed
Now, the master branch and feature1 branch become the following figure:
Using git log with parameters, you can also see the merging of branches:
$ git log --graph --pretty=oneline --abbrev-commit * cf810e4 (HEAD -> master) conflict fixed |\ | * 14096d0 (feature1) AND simple * | 5dc6824 & simple |/ * b17d20e branch test * d46f35e (origin/master) remove test.txt * b84166e add test.txt * 519219b git tracks changes * e43a48b understand how stage works * 1094adb append GPL * e475afc add distributed * eaadf4e wrote a readme file
Finally, delete the feature1 branch:
$ git branch -d feature1 Deleted branch feature1 (was 14096d0).
completion of jobs.
Summary
When Git cannot automatically merge branches, the conflict must be resolved first. After resolving the conflict, submit and merge.
Conflict resolution is to manually edit the failed Git merge file to the content we want, and then submit it.
Use the git log --graph command to see the branch merge diagram.
Branch management strategy
Usually, when merging branches, Git will use Fast forward mode if possible, but in this mode, branch information will be lost after deleting branches.
If the Fast forward mode is to be forcibly disabled, Git will generate a new commit when merging, so that the branch information can be seen from the branch history.
Let's practice -- git merge in no FF mode:
First, still create and switch the dev branch:
$ git checkout -b dev Switched to a new branch 'dev'
Modify readme Txt file and submit a new commit:
$ git add readme.txt $ git commit -m "add merge" [dev f52c633] add merge 1 file changed, 1 insertion(+)
Now, let's switch back to master:
$ git checkout master Switched to branch 'master'
When preparing to merge dev branches, please note the -- no FF parameter, which means that Fast forward is disabled:
$ git merge --no-ff -m "merge with no-ff" dev Merge made by the 'recursive' strategy. readme.txt | 1 + 1 file changed, 1 insertion(+)
Because a new commit will be created in this merge, add the - m parameter to write the commit description.
After merging, let's use git log to see the branch history:
$ git log --graph --pretty=oneline --abbrev-commit * e1e9c68 (HEAD -> master) merge with no-ff |\ | * f52c633 (dev) add merge |/ * cf810e4 conflict fixed ...
It can be seen that without using the Fast forward mode, the merge is like this:
Branching strategy
In actual development, we should carry out branch management according to several basic principles:
First, the master branch should be very stable, that is, it is only used to release new versions and cannot work on it at ordinary times;
Where do you work? Work on the dev branch, that is, the dev branch is unstable. At some time, for example, when version 1.0 is released, merge the dev branch into the master, and release version 1.0 in the master branch;
You and your friends, everyone works on the dev branch. Everyone has their own branch. Just merge on the dev branch from time to time.
So the branch of teamwork looks like this:
Summary
Git branch is very powerful and should be fully applied in team development.
When merging branches, add the -- no FF parameter to merge in the normal mode. After merging, there are branches in the history. It can be seen that merging has been done, while fast forward merging can not see that merging has been done.
Bug branch
In software development, bugs are just as common. Bugs need to be repaired. In Git, because branches are so powerful, each bug can be repaired through a new temporary branch. After repair, merge the branches, and then delete the temporary branch.
When you receive a task to fix a bug code 101, naturally, you want to create a branch issue-101 to fix it, but wait, the current work on dev has not been submitted:
$ git status On branch dev Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: hello.py Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt
It's not that you don't want to submit, but that the work is only halfway through and can't be submitted. It's expected to take another day to complete. However, the bug must be fixed within two hours. What should I do?
Fortunately, Git also provides a stash function, which can "store" the current work site and continue to work after restoring the site in the future:
$ git stash Saved working directory and index state WIP on dev: f52c633 add merge
Now, viewing the workspace with git status is clean (unless there are files that are not managed by Git), so you can safely create branches to fix bug s.
First, determine which branch you want to fix the bug on. If you need to fix it on the master branch, create a temporary branch from the master:
$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 6 commits. (use "git push" to publish your local commits) $ git checkout -b issue-101 Switched to a new branch 'issue-101'
To fix the bug, change "Git is free software..." to "Git is a free software...", and then submit:
$ git add readme.txt $ git commit -m "fix bug 101" [issue-101 4c805e2] fix bug 101 1 file changed, 1 insertion(+), 1 deletion(-)
After the repair, switch to the master branch, complete the merge, and finally delete the issue-101 branch:
$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 6 commits. (use "git push" to publish your local commits) $ git merge --no-ff -m "merged bug fix 101" issue-101 Merge made by the 'recursive' strategy. readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Great, the original two-hour bug fix took only five minutes! Now, it's time to go back to the dev branch!
$ git checkout dev Switched to branch 'dev' $ git status On branch dev nothing to commit, working tree clean
The work area is clean. Where was the work site just now? Use git stash list command to see:
$ git stash list stash@{0}: WIP on dev: f52c633 add merge
The job site is still there. Git has stored the stash content somewhere, but it needs to be restored. There are two ways:
First, restore with git stash apply, but after restoration, the stash content will not be deleted. You need to use git stash drop to delete it;
Another way is to use git stash pop to delete the stash content while restoring:
$ git stash pop On branch dev Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: hello.py Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt Dropped refs/stash@{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a)
Then use git stash list to view, and you can't see any stash content:
$ git stash list
You can stash multiple times. When restoring, first check with git stash list, and then restore the specified stash with the command:
$ git stash apply stash@{0}
After fixing the bug on the master branch, let's consider that the dev branch was separated from the master branch earlier, so this bug also exists on the current dev branch.
How can I fix the same bug on the dev branch? Repeat the operation once and submit it?
Is there a simpler way to have wood?
have
To fix the same bug on dev, we only need to "copy" the changes made by 4c805e2 fix bug 101 submission to the dev branch. Note: we only want to copy the changes made by the submission of 4c805e2 fix bug 101, not merge the whole master branch.
To facilitate operation, Git specifically provides a cherry pick command, which allows us to copy a specific commit to the current branch:
$ git branch * dev master $ git cherry-pick 4c805e2 [master 1d4b803] fix bug 101 1 file changed, 1 insertion(+), 1 deletion(-)
Git automatically makes a commit to the dev branch. Note that the commit submitted this time is 1d4b803, which is not different from 4c805e2 of the master, because the two commit changes are the same, but they are two different commit. With git cherry pick, we don't need to manually repeat the bug fixing process on the dev branch.
Some smart children's shoes will think that since you can "replay" the repair process on the dev branch after repairing the bug on the master branch, can you repair the bug directly on the dev branch and then "replay" on the master branch? Sure, but you still need the git stash command to save the scene before you can switch from the dev branch to the master branch.
Summary
When fixing a bug, we will create a new bug branch to fix it, then merge and delete it;
When the work at hand is not finished, first git stash the work site, then fix the bug, and then git stash pop to return to the work site;
If you want to merge the bug fixed on the master branch into the current dev branch, you can use the GIT cherry pick < commit > command to "copy" the modification submitted by the bug to the current branch to avoid repeated work.
Feature branch
In software development, there are always endless new functions to be added.
When adding a new function, you certainly don't want to mess up the main branch because of some experimental code. Therefore, every time you add a new function, you'd better create a new feature branch, develop it on it, merge it after completion, and finally delete the feature branch.
Now, you finally have a new task: developing a new feature code named Vulcan, which is planned for the next generation of starships.
So we are ready to develop:
$ git checkout -b feature-vulcan Switched to a new branch 'feature-vulcan'
After 5 minutes, the development is completed:
$ git add vulcan.py $ git status On branch feature-vulcan Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: vulcan.py $ git commit -m "add feature vulcan" [feature-vulcan 287773e] add feature vulcan 1 file changed, 2 insertions(+) create mode 100644 vulcan.py
Switch back to dev and prepare for merging:
$ git checkout dev
If everything goes well, the feature branch and bug branch are similar. Merge and delete them.
But!
At this time, after receiving the order from the superior, the new function must be cancelled due to insufficient funds!
Although it was done in vain, this branch containing confidential information must be destroyed on site:
$ git branch -d feature-vulcan error: The branch 'feature-vulcan' is not fully merged. If you are sure you want to delete it, run 'git branch -D feature-vulcan'.
Destroy failed. Git kindly reminds that the feature Vulcan branch has not been merged. If it is deleted, the modification will be lost. If it is to be forcibly deleted, the capitalized - D parameter needs to be used..
Now let's forcibly delete:
$ git branch -D feature-vulcan Deleted branch feature-vulcan (was 287773e).
Finally deleted successfully!
Summary
To develop a new feature, it is best to create a new branch;
If you want to discard a branch that has not been merged, you can forcibly delete it through git branch - d < name >.
Multi person collaboration
When you clone from a remote warehouse, in fact, Git automatically corresponds the local master branch to the remote master branch, and the default name of the remote warehouse is origin.
To view the information of the remote library, use git remote:
$ git remote origin
Alternatively, use git remote -v to display more detailed information:
$ git remote -v origin git@github.com:michaelliao/learngit.git (fetch) origin git@github.com:michaelliao/learngit.git (push)
The address of the origin that can be crawled and pushed is shown above. If you don't have push permission, you can't see the push address.
Push branch
Push branch is to push all local submissions on the branch to the remote library. When pushing, specify the local branch, so Git will push the branch to the remote branch corresponding to the remote library:
$ git push origin master
If you want to push other branches, such as dev, change to:
$ git push origin dev
However, it is not necessary to push the local branches to the remote, so which branches need to be pushed and which do not?
-
The master branch is the main branch, so it should be synchronized with the remote branch at all times;
-
dev branch is a development branch. All members of the team need to work on it, so they also need to synchronize with remote;
-
The bug branch is only used to fix bugs locally, so there is no need to push it to the remote, unless the boss wants to see how many bugs you fix every week;
-
Whether the feature branch is pushed to the remote depends on whether you develop it with your small partners.
In short, in Git, branches can hide and play locally. Whether to push depends on your mood!
Grab branch
When multiple people collaborate, everyone will push their own modifications to the master and dev branches.
Now, simulate your little partner and clone it on another computer (note to add SSH Key to GitHub) or in another directory of the same computer:
$ git clone git@github.com:michaelliao/learngit.git Cloning into 'learngit'... remote: Counting objects: 40, done. remote: Compressing objects: 100% (21/21), done. remote: Total 40 (delta 14), reused 40 (delta 14), pack-reused 0 Receiving objects: 100% (40/40), done. Resolving deltas: 100% (14/14), done.
When your partner clone s from a remote database, by default, your partner can only see the local master branch. If you don't believe it, you can use the git branch command to see:
$ git branch * master
Now, if your little partner wants to develop on the dev branch, he must create the dev branch of the remote origin to the local, so he uses this command to create the local dev branch:
$ git checkout -b dev origin/dev
Now, he can continue to modify on dev, and then push the dev branch to the remote from time to time:
$ git add env.txt $ git commit -m "add env" [dev 7a5e5dd] add env 1 file changed, 1 insertion(+) create mode 100644 env.txt $ git push origin dev Counting objects: 3, done. Delta compression using up to 4 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 308 bytes | 308.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To github.com:michaelliao/learngit.git f52c633..7a5e5dd dev -> dev
Your little partner has pushed his submission to the origin/dev branch, and it happens that you have also modified the same file and tried to push:
$ cat env.txt env $ git add env.txt $ git commit -m "add new env" [dev 7bd91f1] add new env 1 file changed, 1 insertion(+) create mode 100644 env.txt $ git push origin dev To github.com:michaelliao/learngit.git ! [rejected] dev -> dev (non-fast-forward) error: failed to push some refs to 'git@github.com:michaelliao/learngit.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
The push failed because there is a conflict between your partner's latest submission and the submission you are trying to push. The solution is also very simple. Git has prompted us to grab the latest Submission from origin/dev with git pull, then merge locally, solve the conflict, and then push:
$ git pull There is no tracking information for the current branch. Please specify which branch you want to merge with. See git-pull(1) for details. git pull <remote> <branch> If you wish to set tracking information for this branch you can do so with: git branch --set-upstream-to=origin/<branch> dev
git pull also failed because the link between the local dev branch and the remote origin/dev branch is not specified. According to the prompt, set the link between Dev and origin/dev:
$ git branch --set-upstream-to=origin/dev dev Branch 'dev' set up to track remote branch 'dev' from 'origin'.
Then pull:
$ git pull Auto-merging env.txt CONFLICT (add/add): Merge conflict in env.txt Automatic merge failed; fix conflicts and then commit the result.
git pull is successful this time, but there are conflicts in the merge, which need to be solved manually. The solution method is exactly the same as that in branch management. After solving the problem, submit and then push:
$ git commit -m "fix env conflict" [dev 57c53ab] fix env conflict $ git push origin dev Counting objects: 6, done. Delta compression using up to 4 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done. Total 6 (delta 0), reused 0 (delta 0) To github.com:michaelliao/learngit.git 7a5e5dd..57c53ab dev -> dev
Therefore, the working mode of multi person cooperation is usually as follows:
-
First, you can try to push your own modifications with git push origin < branch name >;
-
If the push fails, you need to use git pull to try to merge because the remote branch is newer than your local branch;
-
If there is a conflict in the merger, resolve the conflict and submit it locally;
-
If there is no conflict or the conflict is solved, then push it with git push origin to succeed!
-
If git pull prompts no tracking information, it indicates that the link relationship between the local branch and the remote branch has not been created. Use the command git branch -- set upstream to origin /.
This is the working mode of multi person cooperation. Once you are familiar with it, it is very simple.
Summary
-
To view the remote library information, use git remote -v;
-
If the newly created local branch is not pushed to the remote, it will not be visible to others;
-
Push the branch locally, and use git push origin branch name. If the push fails, first grab the remote new submission with git pull;
-
Create a branch corresponding to the remote branch locally. Use git checkout - B branch name origin / branch name. The names of the local and remote branches should be the same;
-
Establish the association between local branch and remote branch, and use git branch -- set upstream branch name origin / branch name;
-
Grab the branch from the remote and use git pull. If there is a conflict, deal with the conflict first.
Rebase
In the previous section, we saw that when multiple people collaborate on the same branch, conflicts are easy to occur. Even if there is no conflict, the post push children's shoes have to be pull ed first, merged locally, and then pushed successfully.
After each merge and push, the branch becomes like this:
$ git log --graph --pretty=oneline --abbrev-commit * d1be385 (HEAD -> master, origin/master) init hello * e5e69f1 Merge branch 'dev' |\ | * 57c53ab (origin/dev, dev) fix env conflict | |\ | | * 7a5e5dd add env | * | 7bd91f1 add new env | |/ * | 12a631b merged bug fix 101 |\ \ | * | 4c805e2 fix bug 101 |/ / * | e1e9c68 merge with no-ff |\ \ | |/ | * f52c633 add merge |/ * cf810e4 conflict fixed
In short, it looks messy. Children's shoes with obsessive-compulsive disorder will ask: why can't Git's submission history be a clean straight line?
In fact, it can be done!
Git has an operation called rebase, which has been translated as "rebase".
Don't imagine at will. Let's start with practical problems and see how to turn the forked submission into a straight line.
After synchronizing with the remote branch, we Py this file has been submitted twice. Use the git log command to see:
$ git log --graph --pretty=oneline --abbrev-commit * 582d922 (HEAD -> master) add author * 8875536 add comment * d1be385 (origin/master) init hello * e5e69f1 Merge branch 'dev' |\ | * 57c53ab (origin/dev, dev) fix env conflict | |\ | | * 7a5e5dd add env | * | 7bd91f1 add new env ...
Note that Git uses (HEAD - > Master) and (origin/master) to identify the positions of the HEAD and remote origin of the current branch, which are 582d922 add author and d1be385 init hello respectively. The local branch commits two times faster than the remote branch.
Now let's try to push the local branch:
$ git push origin master To github.com:michaelliao/learngit.git ! [rejected] master -> master (fetch first) error: failed to push some refs to 'git@github.com:michaelliao/learngit.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Unfortunately, it failed, which indicates that someone pushed the remote branch before us. According to experience, first pull:
$ git pull remote: Counting objects: 3, done. remote: Compressing objects: 100% (1/1), done. remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0 Unpacking objects: 100% (3/3), done. From github.com:michaelliao/learngit d1be385..f005ed4 master -> origin/master * [new tag] v1.0 -> v1.0 Auto-merging hello.py Merge made by the 'recursive' strategy. hello.py | 1 + 1 file changed, 1 insertion(+)
Then use git status to see the status:
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean
In addition to the submissions just merged, now our local branch is 3 submissions ahead of the remote branch.
Use git log to see:
$ git log --graph --pretty=oneline --abbrev-commit * e0ea545 (HEAD -> master) Merge branch 'master' of github.com:michaelliao/learngit |\ | * f005ed4 (origin/master) set exit=1 * | 582d922 add author * | 8875536 add comment |/ * d1be385 init hello ...
For children's shoes with obsessive-compulsive disorder, things are a little wrong now, and the submission of history is forked. If you push the local branch to the remote now, is there a problem?
have
What's the problem?
disgraceful!
Is there a solution?
have
At this time, rebase comes in handy. Let's try the command git rebase:
$ git rebase First, rewinding head to replay your work on top of it... Applying: add comment Using index info to reconstruct a base tree... M hello.py Falling back to patching base and 3-way merge... Auto-merging hello.py Applying: add author Using index info to reconstruct a base tree... M hello.py Falling back to patching base and 3-way merge... Auto-merging hello.py
A lot of operations are output. What is the effect? Then use git log to see:
$ git log --graph --pretty=oneline --abbrev-commit * 7e61ed4 (HEAD -> master) add author * 3611cfe add comment * f005ed4 (origin/master) set exit=1 * d1be385 init hello ...
The original bifurcated submission has now become a straight line! How is this magical operation realized? In fact, the principle is very simple. We noticed that Git "moved" our local submission to f005ed4 (origin/master) set exit=1. In this way, the whole submission history becomes a straight line. Before and after rebase operation, the final submission content is consistent. However, the local commit modification content has changed. Their modification is no longer based on d1be385 init hello, but based on f005ed4 (origin/master) set exit=1, but the final submission 7e61ed4 content is consistent.
This is the characteristic of rebase operation: it "arranges" the forked submission history into a straight line, which looks more intuitive. The disadvantage is that the local fork submission has been modified.
Finally, push the local branch to the remote branch through the push operation:
Mac:~/learngit michael$ git push origin master Counting objects: 6, done. Delta compression using up to 4 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done. Total 6 (delta 2), reused 0 (delta 0) remote: Resolving deltas: 100% (2/2), completed with 1 local object. To github.com:michaelliao/learngit.git f005ed4..7e61ed4 master -> master
Then use git log to see the effect:
$ git log --graph --pretty=oneline --abbrev-commit * 7e61ed4 (HEAD -> master, origin/master) add author * 3611cfe add comment * f005ed4 set exit=1 * d1be385 init hello ...
The commit history of remote branches is also a straight line.
Summary
-
rebase can sort out the local non push ed bifurcation submission history into a straight line;
-
The purpose of rebase is to make it easier for us to view the changes of historical submissions, because forked submissions require tripartite comparison.