Git - 分支管理
Git - 管理分支
Section titled “Git - 管理分支”Git 中的 branch(分支)非常轻量且是现代开发工作流程的基础。一个分支代表了一个独立的开发线。你可以使用分支来处理新功能、bug 修复或实验,而不会影响主代码库(例如,main 分支)。一旦在一个分支上的工作完成,就可以将其合并(merge)回主分支。
例如,如果你正在从 main 分支发布软件的 1.0 版本,你可能会创建一个 develop 分支用于 2.0 版本的功能,并从 develop 创建独立的功能分支(feature branches)。同时,1.0 版本的 bug 修复可以在从 main 创建的 hotfix 分支上进行。
Tom 想创建一个名为 new-feature 的新分支。他可以使用 git branch <branch-name> 命令。这会创建指向当前 commit (HEAD) 的新分支,但不会切换到它。
[tom@dev-machine project/src]$ git branch new-feature
[tom@dev-machine project/src]$ git branch* main new-featuregit branch 命令列出所有本地分支。星号 * 指示当前已 checkout(检出)的分支。从视觉上看,如果 main 在 commit C3:... -> C1 -> C2 -> C3 (HEAD -> main)。执行 git branch new-feature 后,它变为:... -> C1 -> C2 -> C3 (HEAD -> main, new-feature)。
Jerry 使用 git switch <branch-name> 命令(或旧的 git checkout <branch-name>)切换到现有分支。这会更新 working directory(工作目录)中的文件,使其与分支指向的 commit 的快照相匹配,并更新 HEAD 指向此分支。
[jerry@dev-machine project/src]$ git switch new-featureSwitched to branch 'new-feature'
[jerry@dev-machine project/src]$ git branch main* new-feature现在,HEAD 指向 new-feature。
快捷方式:创建并切换分支
Section titled “快捷方式:创建并切换分支”一个常见的工作流程是创建新分支并立即切换到它。你可以使用 git switch -c <branch-name> 或 git checkout -b <branch-name> 在一步内完成。
[jerry@dev-machine project/src]$ git switch -c test-branchSwitched to a new branch 'test-branch'
[jerry@dev-machine project/src]$ git branch main new-feature* test-branch一旦 feature branch(功能分支)已合并且不再需要,你可以使用 git branch -d <branch-name> 删除它。-d 选项仅在分支的更改已合并时才删除分支。使用 -D 可以强制删除一个未合并的分支(请谨慎使用)。
Jerry 当前在 test-branch 上,想删除它。他首先切换到另一个分支(例如 main)。
[jerry@dev-machine project/src]$ git branch main new-feature* test-branch
[jerry@dev-machine project/src]$ git switch mainSwitched to branch 'main'
[jerry@dev-machine project/src]$ git branch -d test-branchDeleted branch test-branch (was 5776472).现在,git branch 将只显示 main 和 new-feature。
要重命名分支,使用 git branch -m <old-name> <new-name>。如果你当前就在想重命名的分支上,可以使用 git branch -m <new-name>。
[jerry@dev-machine project/src]$ git branch* main new-feature
[jerry@dev-machine project/src]$ git branch -m new-feature feature/wchar-support
[jerry@dev-machine project/src]$ git branch* main feature/wchar-supportMerging(合并)是将一个分支的更改集成到另一个分支中。通常,你会将一个功能分支合并回你的主开发分支(例如 main 或 develop)。
Jerry 一直在 feature/wchar-support 分支上工作,并实现了一个 w_strlen 函数。将更改提交到此分支后,历史记录可能如下所示:...C2 -> C3 (main) -> C4 -> C5 (HEAD -> feature/wchar-support),其中 C4 和 C5 是该功能分支上的 commit。
他在 feature/wchar-support 上提交了他的更改:
[jerry@dev-machine src]$ git switch feature/wchar-support[jerry@dev-machine src]$ # ... makes changes to string_operations.c ...[jerry@dev-machine src]$ git add string_operations.c[jerry@dev-machine src]$ git commit -m "Added w_strlen for wide char support"[feature/wchar-support 64192f9] Added w_strlen for wide char support 1 file changed, 10 insertions(+)
[jerry@dev-machine src]$ git push origin feature/wchar-supportTom 想将 Jerry 的 w_strlen 函数集成到 main 分支中。首先,Tom 确保他的 main 分支是最新的,然后切换到 main。然后他使用 git merge。
[tom@dev-machine project]$ git switch mainSwitched to branch 'main'[tom@dev-machine project]$ git pull origin main # Ensure main is up-to-date
[tom@dev-machine project]$ git fetch origin # Fetch latest changes from remote, including Jerry's branch
[tom@dev-machine project]$ git merge origin/feature/wchar-supportUpdating 5776472..64192f9Fast-forward src/string_operations.c | 10 ++++++++++ 1 file changed, 10 insertions(+)在这种情况下,Git 执行了 ‘fast-forward’(快进)合并。这发生在自创建以来 main 分支没有从 feature/wchar-support 分支分叉的情况下。main 只是简单地将其指针向前移动到 feature/wchar-support 的最新 commit。历史记录变成线性的:...C2 -> C3 -> C4 -> C5 (HEAD -> main, origin/feature/wchar-support)。
如果 main 有 feature/wchar-support 中不存在的新 commit,Git 会创建一个新的 ‘merge commit’(合并提交)来将两个历史记录连接起来。这个 commit 有两个 parent(父)commit。
测试后,Tom 将更新的 main 分支推送到 remote(远程仓库):
[tom@dev-machine project]$ git push origin main变基(Rebase)分支
Section titled “变基(Rebase)分支”git rebase 是将一个分支的更改集成到另一个分支的另一种方式。与创建合并提交不同,rebase 通过重写 commit 历史来实现:它将你当前分支上的所有 commit 取出,然后逐一地将它们在另一个分支(base,基础分支)的顶端重新应用。这个过程会创建新的 commit ID。
想象一下你的 main 分支有 commit A-B-C。你从 C 分支出来创建了 my-feature 并添加了 commit X-Y。所以 my-feature 的历史是 A-B-C-X-Y。与此同时,main 分支通过新的 commit D-E 前进了,所以 main 的历史是 A-B-C-D-E。
如果你在 my-feature 分支上运行 git rebase main,Git 会取出你的 commit X-Y,然后将它们重新应用在 main 的最新 commit E 的顶端。你的 my-feature 分支现在看起来像 A-B-C-D-E-X’-Y’(X’ 和 Y’ 是新的 commit,内容相同但 ID 不同,因为它们的基础改变了)。这会产生一个线性的历史记录,一些团队更喜欢这种方式。
示例:[jerry@dev-machine project]$ git switch my-feature 然后 [jerry@dev-machine project]$ git rebase main。
警告:Rebasing 会重写历史记录。切勿对已推送到共享 remote 分支且正在被他人使用的 commit 进行 rebase,因为它会导致他们的数据不一致并产生问题。通常,对你自己的尚未共享的本地分支进行 rebase 是安全的,或者在合并之前将功能分支 rebase 到更新的主/开发分支上(通常通过 git pull --rebase 完成)。