分支(Branch)是 Git 中一个核心概念,它允许开发者在不影响主代码库的情况下,同时进行多个独立的开发线

Git Branching - Branches in a Nutshell

分支(Branch)是 Git 中一个核心概念,它允许开发者在不影响主代码库的情况下,同时进行多个独立的开发线。以下是关于 Git 分支的简要介绍:

一、分支的基本概念

  1. 分支的定义

    • 分支在 Git 中是一个指向提交对象的指针。每次提交时,Git 都会保存一个快照并记录一个指向该快照的指针。分支就是这个指针的名字。
  2. 分支的作用

    • 分支用于隔离开发工作。例如,开发者可以在一个分支上开发新功能,在另一个分支上修复错误,而不会相互干扰。

二、分支的创建与管理

  1. 创建分支

    • 可以使用 git branch <branch-name> 命令创建一个新的分支,但不会自动切换到该分支。
    • 要创建一个新分支并切换到它,可以使用 git checkout -b <branch-name> 命令。
  2. 查看分支

    • 使用 git branch 命令可以查看本地分支,当前所在的分支会有一个星号(*)标记。
    • 使用 git branch -r 命令可以查看远程分支。
    • 使用 git branch -a 命令可以查看所有分支(包括本地和远程分支)。
  3. 切换分支

    • 可以使用 git checkout <branch-name> 命令切换到指定的分支。
    • 在 Git 2.23 及以上版本,可以使用 git switch <branch-name> 命令来切换分支。
  4. 删除分支

    • 使用 git branch -d <branch-name> 命令可以删除已经合并的分支。
    • 如果分支尚未合并,可以使用 git branch -D <branch-name> 命令强制删除。

三、分支的合并

  1. 合并分支

    • 当在某个分支上完成了工作,并希望将这些更改合并回主分支时,可以使用 git checkout <main-branch> 命令切换到主分支,然后使用 git merge <branch-name> 命令进行合并。
  2. 合并模式

    • Fast-Forward(快进式):当两个分支的提交历史是线性关系时,Git 会使用快进式合并,只是简单地移动指针。
    • Recursive Strategy Merge(策略合并式):当两个分支的提交历史出现分叉时,Git 会使用三方合并策略,创建一个新的提交来包含合并后的结果。
  3. 解决冲突

    • 在合并过程中,如果两个分支对同一个文件的同一个部分进行了修改,Git 会提示冲突。此时,需要手动解决冲突,然后使用 git add <file> 命令标记冲突已解决,最后使用 git commit 命令完成合并。

四、分支的优势

Git 的分支模型非常轻量级,创建、切换和删除分支的操作都非常快速。这使得 Git 鼓励频繁地分支和合并,即使在一天中多次进行,也不会影响性能。

五、分支的最佳实践

  1. 保持主分支的稳定

    • 主分支(通常是 mainmaster)应保持可部署的状态,避免在主分支上进行直接开发。
  2. 使用功能分支

    • 为每个新功能或修复创建一个新的分支,开发完成后合并回主分支。
  3. 定期合并和测试

    • 定期将功能分支合并回主分支,并进行全面的测试,以确保代码的稳定性。

总结

分支是 Git 中一个非常重要的功能,它允许开发者并行工作,同时保持代码库的整洁和有序。掌握 Git 分支的基本操作和管理技巧,可以显著提高开发效率和代码质量。

Nearly every VCS has some form of branching support. Branching means you diverge from the main line of development and continue to do work without messing with that main line. In many VCS tools, this is a somewhat expensive process, often requiring you to create a new copy of your source code directory, which can take a long time for large projects.

Some people refer to Git’s branching model as its “killer feature,” and it certainly sets Git apart in the VCS community. Why is it so special? The way Git branches is incredibly lightweight, making branching operations nearly instantaneous, and switching back and forth between branches generally just as fast. Unlike many other VCSs, Git encourages workflows that branch and merge often, even multiple times in a day. Understanding and mastering this feature gives you a powerful and unique tool and can entirely change the way that you develop.
Branches in a Nutshell

To really understand the way Git does branching, we need to take a step back and examine how Git stores its data.

As you may remember from Getting Started, Git doesn’t store data as a series of changesets or differences, but instead as a series of snapshots.

When you make a commit, Git stores a commit object that contains a pointer to the snapshot of the content you staged. This object also contains the author’s name and email address, the message that you typed, and pointers to the commit or commits that directly came before this commit (its parent or parents): zero parents for the initial commit, one parent for a normal commit, and multiple parents for a commit that results from a merge of two or more branches.

To visualize this, let’s assume that you have a directory containing three files, and you stage them all and commit. Staging the files computes a checksum for each one (the SHA-1 hash we mentioned in Getting Started), stores that version of the file in the Git repository (Git refers to them as blobs), and adds that checksum to the staging area:

$ git add README test.rb LICENSE
$ git commit -m ‘Initial commit’

When you create the commit by running git commit, Git checksums each subdirectory (in this case, just the root project directory) and stores them as a tree object in the Git repository. Git then creates a commit object that has the metadata and a pointer to the root project tree so it can re-create that snapshot when needed.

Your Git repository now contains five objects: three blobs (each representing the contents of one of the three files), one tree that lists the contents of the directory and specifies which file names are stored as which blobs, and one commit with the pointer to that root tree and all the commit metadata.
A commit and its tree.
Figure 9. A commit and its tree

If you make some changes and commit again, the next commit stores a pointer to the commit that came immediately before it.
Commits and their parents.
Figure 10. Commits and their parents

A branch in Git is simply a lightweight movable pointer to one of these commits. The default branch name in Git is master. As you start making commits, you’re given a master branch that points to the last commit you made. Every time you commit, the master branch pointer moves forward automatically.
Note

The “master” branch in Git is not a special branch. It is exactly like any other branch. The only reason nearly every repository has one is that the git init command creates it by default and most people don’t bother to change it.
A branch and its commit history.
Figure 11. A branch and its commit history
Creating a New Branch

What happens when you create a new branch? Well, doing so creates a new pointer for you to move around. Let’s say you want to create a new branch called testing. You do this with the git branch command:

$ git branch testing

This creates a new pointer to the same commit you’re currently on.
Two branches pointing into the same series of commits.
Figure 12. Two branches pointing into the same series of commits

How does Git know what branch you’re currently on? It keeps a special pointer called HEAD. Note that this is a lot different than the concept of HEAD in other VCSs you may be used to, such as Subversion or CVS. In Git, this is a pointer to the local branch you’re currently on. In this case, you’re still on master. The git branch command only created a new branch — it didn’t switch to that branch.
HEAD pointing to a branch.
Figure 13. HEAD pointing to a branch

You can easily see this by running a simple git log command that shows you where the branch pointers are pointing. This option is called --decorate.

$ git log --oneline --decorate
f30ab (HEAD -> master, testing) Add feature #32 - ability to add new formats to the central interface
34ac2 Fix bug #1328 - stack overflow under certain conditions
98ca9 Initial commit

You can see the master and testing branches that are right there next to the f30ab commit.
Switching Branches

To switch to an existing branch, you run the git checkout command. Let’s switch to the new testing branch:

$ git checkout testing

This moves HEAD to point to the testing branch.
HEAD points to the current branch.
Figure 14. HEAD points to the current branch

What is the significance of that? Well, let’s do another commit:

$ vim test.rb
$ git commit -a -m ‘made a change’

The HEAD branch moves forward when a commit is made.
Figure 15. The HEAD branch moves forward when a commit is made

This is interesting, because now your testing branch has moved forward, but your master branch still points to the commit you were on when you ran git checkout to switch branches. Let’s switch back to the master branch:

$ git checkout master

Note

git log doesn’t show all the branches all the time

If you were to run git log right now, you might wonder where the “testing” branch you just created went, as it would not appear in the output.

The branch hasn’t disappeared; Git just doesn’t know that you’re interested in that branch and it is trying to show you what it thinks you’re interested in. In other words, by default, git log will only show commit history below the branch you’ve checked out.

To show commit history for the desired branch you have to explicitly specify it: git log testing. To show all of the branches, add --all to your git log command.
HEAD moves when you checkout.
Figure 16. HEAD moves when you checkout

That command did two things. It moved the HEAD pointer back to point to the master branch, and it reverted the files in your working directory back to the snapshot that master points to. This also means the changes you make from this point forward will diverge from an older version of the project. It essentially rewinds the work you’ve done in your testing branch so you can go in a different direction.
Note

Switching branches changes files in your working directory

It’s important to note that when you switch branches in Git, files in your working directory will change. If you switch to an older branch, your working directory will be reverted to look like it did the last time you committed on that branch. If Git cannot do it cleanly, it will not let you switch at all.

Let’s make a few changes and commit again:

$ vim test.rb
$ git commit -a -m ‘made other changes’

Now your project history has diverged (see Divergent history). You created and switched to a branch, did some work on it, and then switched back to your main branch and did other work. Both of those changes are isolated in separate branches: you can switch back and forth between the branches and merge them together when you’re ready. And you did all that with simple branch, checkout, and commit commands.
Divergent history.
Figure 17. Divergent history

You can also see this easily with the git log command. If you run git log --oneline --decorate --graph --all it will print out the history of your commits, showing where your branch pointers are and how your history has diverged.

$ git log --oneline --decorate --graph --all

  • c2b9e (HEAD, master) Made other changes
    | * 87ab2 (testing) Made a change
    |/
  • f30ab Add feature #32 - ability to add new formats to the central interface
  • 34ac2 Fix bug #1328 - stack overflow under certain conditions
  • 98ca9 initial commit of my project

Because a branch in Git is actually a simple file that contains the 40 character SHA-1 checksum of the commit it points to, branches are cheap to create and destroy. Creating a new branch is as quick and simple as writing 41 bytes to a file (40 characters and a newline).

This is in sharp contrast to the way most older VCS tools branch, which involves copying all of the project’s files into a second directory. This can take several seconds or even minutes, depending on the size of the project, whereas in Git the process is always instantaneous. Also, because we’re recording the parents when we commit, finding a proper merge base for merging is automatically done for us and is generally very easy to do. These features help encourage developers to create and use branches often.

Let’s see why you should do so.
Note

Creating a new branch and switching to it at the same time

It’s typical to create a new branch and want to switch to that new branch at the same time — this can be done in one operation with git checkout -b .
Git --distributed-even-if-your-workflow-isnt

About
Documentation
    Reference
    Book
    Videos
    External Links
Downloads
Community

This book is available in English.

Full translation available in
български език,
Deutsch,
Español,
Français,
Ελληνικά,
日本語,
한국어,
Nederlands,
Русский,
Slovenščina,
Tagalog,
Українська
简体中文,

Partial translations available in
Čeština,
Македонски,
Polski,
Српски,
Ўзбекча,
繁體中文,

Translations started for
azərbaycan dili,
Беларуская,
فارسی,
Indonesian,
Italiano,
Bahasa Melayu,
Português (Brasil),
Português (Portugal),
Svenska,
Türkçe.

The source of this book is hosted on GitHub.
Patches, suggestions and comments are welcome.
Chapters ▾ 2nd Edition
3.1 Git Branching - Branches in a Nutshell
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值