Git's (iv) branch management

Source: Internet
Author: User
Tags save file version control system

When we initialize the Git repository, Git creates a main branch called Master by default. In the actual work, the main branch requirement is a stable, robust, secure main line, generally do not allow direct development on the main branch, but pull a new branch, development, testing completed, and then merge the branch into the main branch.

Using branching means that you can detach from the development main line and then continue to work without affecting the mainline. In many version control systems, this is an expensive process and often requires creating a full copy of the source code directory, which can take a long time for large projects.

Git's branching model can be called a "kill feature", which distinguishes git from the version control system family. Other version control systems such as SVN have branch management, but after use you will find that these version control system creation and switching branches than the snail is still slow, it is unbearable, the results branch function became a device, we do not use. But git's branches are different, and git can do it instantly, no matter how you create, switch, and delete branches. Whether your repository is 1 files or 10,000 files.

Git encourages frequent use of branching and merging in the workflow, even if it does not matter many times in a single day. In the actual work, often fix a bug will use a branch to complete.

Once you understand the concept of branching and use it skillfully, you will realize why Git is such a powerful and unique tool that really changes the way you develop.

Branching implementation principle

As mentioned in the first article, Git doesn't save file differences or changes, but just a series of file snapshots.

When committed in Git, a commit object is saved that contains a pointer to a snapshot of the staging content, including related ancillary information such as the author of the submission, and contains 0 or more pointers to the parent object of the commit: the first commit is not a direct ancestor, and the ordinary commits have an ancestor, A commit that is produced by merging two or more branches has multiple ancestors.

For the sake of intuition, we assume that there are three files in the working directory that are ready to be submitted after they are staged. The staging operation calculates a checksum (that is, the SHA-1 hash string) for each file, and then saves the current version of the file snapshot to the Git repository (git uses blob-type objects to store the snapshots) and officer and joins the staging area.

When you use Git commit to create a new commit object, Git calculates the checksum for each subdirectory (in this case, the project root) and then saves those directories as tree objects in the Git repository. After that, Git creates a commit object that contains pointers to the tree object (the project root), in addition to the relevant commit information, so that it can reproduce the snapshot's contents in the future.

Now, there are five objects in the Git repository: Three Blob objects representing the contents of the file snapshot, a tree object that records the contents of the directory tree and the index of each file corresponding to the Blob object, and a commit object that contains the index and other commit information metadata that points to the tree object (root directory):

Make some changes and commit again, this time the commit object will contain a pointer to the last commit object (that is, the parent object in). After two commits, the warehouse history will look like this:

A branch in Git is essentially a mutable pointer to a commit object . Git uses master as the default name for the branch. After several commits, there is actually a master branch that points to the last commit object, which automatically moves forward each time the commit occurs.

Create a branch

To create a new branch named "Testing", you can use the "git branch<branchname>" command:

Git branch Testing

This command creates a new pointer on the current commit object:

So, how does Git know which branch you're currently working on? In fact, the answer is simple, it holds a special pointer called HEAD . In Git, it's a pointer to the local branch that is working (you can think of the HEAD as the alias of the current branch). Running the git branch command simply creates a new branch, but does not automatically switch to that branch, so in this case we still work in the Master branch.

Use thegit branchcommand without any parameters to view the current branch situation:

* Master  Testing

Git shows that there are two branches, the current working branch is master, the asterisk "*" in the branch list is equivalent to the head pointer, and the current work branch is labeled.

Switch branches

Command "git checkout <branchName>" To switch the current work branch to a branch named Branchname. For example, run the command:

git checkout Testing

Git will prompt you:

Switched to branch ' testing '

So HEAD points to the testing branch:

Now if we modify the workspace file, all commit actions are committed to the testing branch, not the master.

Now the testing branch moves one step forward, while the master branch still points to the commit object where the original Git checkout was. Now switch back to the master branch:

git checkout Master

This order has done two things. It moves the HEAD pointer back to the master branch and replaces the work area file with the snapshot content pointed to by the Master branch. in other words, the changes that start now will begin with an older version of this project. Its main function is to temporarily cancel the changes made in the testing branch so that you can develop in another direction.

Make some changes on the Mast branch and submit. Now we have a fork in the project submission history, because we just created a branch testing, transformed it into something that did some work, and then went back to the original master branch to do something else.

These changes are isolated in separate branches. We can switch back and forth in different branches and merge them together when the time is ripe.

Because a branch in Git is actually just a file containing the checksum of the object (40 character length SHA-1 string), creating and destroying a branch becomes very inexpensive. To put it bluntly, creating a new branch is to write 41 bytes to a file (plus a newline character) so simple and, of course, fast.

Merging branches

Simulate a scene like this, the morning to the company received a new task, a new branch called "iss53" to do the development work. To create a new and switch to this branch, run git checkout and add the-B parameter:

Git checkout-b iss53

This is equivalent to executing the following two commands:

GIT branch iss53git Checkout iss53

Then write the code constantly, commit the code:

Suddenly, a serious bug on the master branch needs to be repaired immediately upon receiving notification.

The first step must be to switch to master. If both the current workspace and staging area are clean, OK, switch back to master directly. But what if the development on the ISS53 branch has not been completed and it is not easy to commit to the repository? Once cut back to the other branches, the workspace and staging area will be emptied and overwritten. In fact, if the workspace or staging area is not clean and there are no changes committed to the repository, Git is not allowed to switch branches, prompting:

Error:your local changes to the following files Wouldbe overwritten by checkout:      readme.txtplease, commit Your change s or stash them before you can switch branches.

The solution to this problem is the git stash command.

The command can get the middle state of the working directory-that is, the modified tracked file and the staged change-and save it to a stack of unfinished changes that can be re-applied at any time.

After running the "git stash" command, the ISS53 branch will be "stored" without a commit change and can be successfully switched to the master branch. To view the existing storage, you can use the Git stash list, which will go to one of these lists:

[Email protected] {0}: WIP on testing:049d078 ... [Email protected] {1}: WIP on testing:c264051 ... [Email protected] {2}: WIP on testing:21d80a5 ...

List all the stash on the branch, and use the command "git stash apply" to revert to the latest stash scene. If you want to apply an earlier storage, you can specify it by name, like this:git stash apply [email protected]{2}. If you do not specify a number, Git uses the most recent storage by default and tries to apply it.

We switched to the master branch and pulled a branch called "hotfix" to fix the bug urgently.

Git checkout-b ' hotfix '

Once fixed, commit to Repository, now Git's branching structure is as follows:

After testing, the bug was successfully repaired, and then the branch needs to be merged into master, first to switch to master, and then to merge the branches using the commandgit merge:

git checkout mastergit Merge hotfix

Git tips:

Updating 771f6de. Adea62afast-forward ...

Note that a "Fast forward" prompt appears when merging. Since the commit object where the current master branch is located is directly upstream of the hotfix branch to be merged, Git simply shifts the master branch pointer directly to the right. In other words, if you go down one branch and you reach another, git will simply move the pointer to the right as it merges the two, because this single-line history branch does not have any differences to resolve, so the merge process can be called Fast Forward (fast forward) .

The most recent modification is now in the commit object pointed to by the current master branch:

After the super-important patch is released, you can go back to the unfinished work. Since the current hotfix branch and master all point to the same commit object, hotfix has completed its historical mission and can be deleted. Use the-d option of Git branch to perform the delete operation:

Git branch-d Hotfix

Don't worry, the changes to the hotfix branch have not yet been included in the iss53. If you do need to include this patch, you can merge the Master branch into iss53 with git merge master, or wait for iss53 to complete before merging the updates from the ISS53 branch into master.

Now go back to work on the previously unfinished ISS53 branch and commit to the repository after the completion.

After you ask the work on the Iss53 branch to complete, you can merge back to the Master branch. The actual operation is similar to the previous Merge hotfix branch, just go back to the master branch and run the git merge command to specify the branch to be merged in.

Note that the underlying implementation of this merge operation differs from the previous hotfix incorporation method. Because this development history is starting from the earlier place forked. Because the Commit object (C4) that the current master branch points to is not the direct ancestor of the ISS53 branch, Git has to do some extra processing. In this case, Git uses the end of the two branches (C4 and C5) and their common ancestor (C2) to perform a simple three-party merge calculation. The three commit objects that Git uses to merge are marked with a red box:

This time, Git does not simply move the branch pointer right, but instead makes a new snapshot of the three-party merge and automatically creates a commit object (C6) that points to it. This commit object is very special, it has two ancestors (C4 and C5).

It is worth mentioning that Git can decide for itself which common ancestor is the best consolidation basis, without the need for developers to manually specify the consolidation base. This feature makes Git's merge operations much simpler than other systems.

Resolve Conflicts

Sometimes merging does not work so well. If you modify the same part of the same file in different branches, Git cannot cleanly combine the two, which logically means that the problem can only be ruled by people. At this point, if you merge the branch, the following result will appear:

Auto-merging readme.txtconflict (content): Merge Conflictin readme.txtautomatic merge failed; Fix conflicts and then committhe result.

Git makes a merge, but does not commit , it will stop waiting for you to resolve the conflict. To see which files conflict when merging, you can use Git status to check:

On branch masteryou has unmerged paths.  (Fix conflictsand run "git commit") unmerged paths:  (use "Gitadd <file> ...." To mark Resolution)      bothmodified:   readme.txtno changes added To commit (use "git add" and/or "Git Commit-a")

Any files that contain unresolved conflicts are listed in the non-consolidated (unmerged) state. Git will include standard conflict resolution tags in conflicting files, which can be used to manually locate and resolve these conflicts. You can see that this file contains a section similar to the following:

This is my first git project<<<<<<

You can see the top half of the ======= partition, which is the content in the HEAD (that is, the branch that the master branch is switching to when the merge command is run), and the lower part is the content in the Iss53 branch. The way to resolve conflicts is to either choose one or you can integrate it yourself. Of course, the extra tag line inserted by Git also needs to be deleted.

After all the conflicts in all the files have been resolved, running git add will mark them as resolved (in effect, one snapshot is saved to the staging area). Because once staged, the conflict is resolved.

Delete Branch

After the branch is merged into master, the branch should be deleted in time if there is no special purpose.

To filter out the list of branches that have been (or have not been) merged with the current branch, you can use the "--merged" and "--no-merged" options.

For example, "git branch--merged" to see which branches have been merged into the current branch, i.e. which branches are directly upstream of the current branch:

* Master  Testing

Prove that the testing branch has been merged into the master branch and can be deleted:

git branch–d Testing

Usegit branch--no-mergeto see the branches that have not yet been merged:


If you use the command "Git branch–d newtesting" to delete the branch, Git prompts:

Error:the branch ' newtesting ' is not fully merged. If you're sure want to delete it, run ' git branch-d newtesting '.

Since these branches also contain work that has not yet been merged, simply deleting the branch with Git branch-d will prompt an error, as doing so will result in loss of data.

However, if you do want to delete the changes on that branch, you can do so with the uppercase delete option-D , as shown in the message above.

Git's (iv) branch management

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.