赞
踩
在版本控制系统中,特别是在使用Git时,冲突(Conflict)指的是当多个团队成员对同一个文件的相同部分进行更改并尝试合并这些更改时发生的问题。冲突通常出现在合并分支、重基(rebase)操作或应用补丁时,因为这些操作涉及将一个分支的更改整合到另一个分支上。
冲突发生的典型情况包括:
编辑冲突:
两个或更多开发者修改了同一个文件的同一部分。例如,如果开发者A删除了一个函数,而开发者B在同一函数中添加了一些新代码,当这两个分支合并时,Git无法自动决定哪个版本是正确的。
文件冲突:
一个开发者修改了一个文件,而另一个开发者删除了同一个文件,或两个开发者重命名/移动了同一个文件但目标不同。
当冲突发生时,Git会标记冲突的文件,并在文件内容中插入特定的标记,指示冲突的位置。这些标记分为以下几部分:
<<<<<<<
:此标记后跟的是当前分支的内容。=======
:分隔当前分支内容和其他分支的内容。>>>>>>>
:此标记后跟的是合并进来的分支的内容。例如,如果在两个分支上对同一文件的同一行进行了不同的更改,Git无法自动合并,文件将包含类似以下内容:
<<<<<<< HEAD
console.log("This is the version in the current branch.");
=======
console.log("This is the version in the branch being merged.");
>>>>>>> feature-branch
解决冲突通常涉及以下步骤:
识别冲突:
使用 git status
查看哪些文件存在冲突。
手动编辑文件:
打开冲突文件,查看冲突标记,并决定保留哪个版本的更改,或者可能合并这两个版本的更改。
标记文件为已解决:
解决完冲突后,使用 git add <file>
命令将文件标记为已解决。这告诉Git您已经手动解决了这些冲突。
完成合并:
一旦所有冲突都被解决并标记,完成合并过程,通常是通过 git commit
命令。通常,Git会提供一个默认的合并提交消息,确认即可。
处理冲突需要细致的注意力,确保合并后的结果符合预期,同时保持代码的功能和完整性。在团队环境中,有效的沟通和代码审查可以大大减少冲突的发生。
在处理不同任务的时候开不同的分支,把不同的任务区别开
多个不同的分支可以合并成一个分支,各个分支互不影响,除非拉取新的更改
为每个任务创建分支是个值得采用的做法,可以更好的追溯变更。
创建新的分支不会更改存储库,只是指出了提交。如下图所示,使用 git branch 命令创建一个名为issue1
的分支,存储库将保持不变,只是为当前提交添加了一个新指针。
git checkout 命令可更新工作树中的文件,以匹配存储在您希望切换到的分支中的版本。类似于切换目录或者工作区。
合并提交中的提交可以有多个父项。
当您在使用Git进行版本控制时,可能会遇到需要在多个分支之间切换的情况,同时又希望保留未提交的更改。这时,Git提供了一些策略来处理这些未提交的更改,以便您可以无碍地在不同分支间进行工作。
基本行为:
冲突防止切换:
为了解决在分支间切换时带来的问题,Git 提供了一个称为 stash
的功能,允许您临时存储未提交的更改,以便您可以清洁地切换到其他分支继续工作。
存储更改:
使用 git stash
或 git stash push
命令将当前工作树中的更改保存起来,这样您的工作树就回到了干净的状态(如同刚刚克隆仓库后的状态)。
git stash
列出存储的更改:
可以通过 git stash list
查看所有存储的更改条目。
git stash list
恢复更改:
当您需要恢复之前存储的更改时,可以使用 git stash pop
(应用最近的更改并从stash列表中移除它)或 git stash apply
(应用更改但保留在stash列表中)。
git stash pop
让我们通过一个具体的例子来说明如何使用 git stash
来管理工作区中未提交的更改,使您能够在不同的分支之间灵活切换。
假设您正在开发一个新功能,在分支 feature-x
上工作。在您开发的过程中,突然接到通知需要立刻解决主分支 main
上的一个紧急bug。
此时,您的工作区有未提交的更改,这些更改还不够稳定,不能直接提交。同时,您需要切换到 main
分支来修复bug。
保存当前更改
在您的 feature-x
分支上,使用以下命令将所有未提交的更改(包括暂存和未暂存的)存入stash:
git stash push -m "WIP: Feature X adjustments"
这里的 -m
选项允许您为stash项添加一个描述性消息,便于以后识别和恢复。
查看Stash列表
输入以下命令查看当前保存的stash项:
git stash list
这会显示所有stash项,包括您刚刚添加的。
切换到主分支
清理了工作区后,您现在可以安全地切换到 main
分支:
git checkout main
进行紧急修复
在 main
分支上进行必要的更改并提交。这可能包括测试、修改和提交修复:
git add .
git commit -m "Fix critical bug in main"
切换回功能分支
修复完成后,切换回您的功能分支:
git checkout feature-x
恢复之前的工作
使用以下命令将之前stashed的更改重新应用到工作区:
git stash pop
这将应用最近的stash项并从stash列表中删除它。
在Git中,快进合并(fast-forward merge)是一种特殊类型的合并,它发生在当一条分支可以直接前进到另一条分支的末端时,无需进行任何实际的合并操作。这种情况通常发生在没有新的并行提交影响这两个分支的情况下,即当前分支的末端提交是要合并分支的基础上直接发展出来的提交。
简化的视图:
当一个分支的所有提交都在另一个分支的直接历史线上时,就可以进行快进合并。这意味着可以简单地将接收分支的指针(HEAD)前移到源分支的最新提交,而不需要创建一个新的合并提交。
没有分支点:
快进合并不会创建一个新的合并提交,因为它仅仅涉及指针的移动。这样做保持了项目历史的线性和简洁。
假设您有两个分支:main
和 feature
。feature
分支从main
分支分出来,main
分支在此期间没有新的提交,而feature
分支有若干提交。当你决定将feature
分支合并回main
分支时:
操作:
git checkout main
git merge feature
结果:
如果main
分支在feature
分出后没有新的提交,Git会执行快进合并,直接将main
分支的HEAD指针移动到feature
分支的最新提交。这样,main
分支现在包含了所有feature
分支的更改。
相对于快进合并,非快进合并发生在当目标分支自分支点以来有新的提交时,即两个分支都有各自独立的提交。在这种情况下,Git无法简单地进行指针前移,因为这样会丢失目标分支上的更改。
操作:
如果你想确保即使可以进行快进合并也要创建一个新的合并提交,可以使用--no-ff
选项:
git merge --no-ff feature
结果:
这将强制Git创建一个新的合并提交,即使是快进合并也不例外。这样做可以保留分支信息和合并历史。
快进合并的优点是保持了历史的清洁和线性,但在某些情况下,保留分支的合并历史(非快进合并)可能更有助于了解项目历史的结构和重要决策。选择使用哪种合并策略取决于团队的偏好和项目的特定需求。
您可以使用 git pull 命令将远程存储库中的最新更改应用到本地存储库。
例如,假设远程分支位于本地分支的上游。远程分支将包含本地分支的所有更改,如下所示。
在这种情况下,如果我们要将远程分支 (origin/main) 的合并应用到我们的本地分支 (main),这将是一个快进合并。
但是如果本地 main 分支中的更改不存在于远程 origin/main 分支中,则拉取命令将执行合并,且将创建将这些更改绑定在一起的合并提交。
执行拉取时,会在本地存储库中自动创建合并提交。如果存在冲突,您将必须解决冲突并手动提交合并。
如果没有冲突,提交将自动合并。
只要没有冲突,在执行拉取时,来自远程分支的更改会自动合并到您当前的本地分支。如果您想获取远程的修改但又不想将它们合并到您当前的本地分支中,您可以执行 git fetch 命令。
获取将从远程下载本地分支上尚不存在的更改。获取FETCH_HEAD ref
将跟踪从远程存储库中获取的更改。
当远程和本地分支都包含不同的后代时,修订历史记录将如下所示:
远程和本地分支具有不同 main 时的修订历史记录。
更改获取后,您可以通过合并获取_HEAD 或执行拉取将这些更改应用到本地存储库。
合并后,更改将应用于本地存储库。
一旦获取FETCH_HEAD
合并,修订历史记录将产生与git pull
操作相同的结果。拉取是同时执行获取和合并操作。
git fetch
vs. git pull
git fetch
git fetch
仅仅从远程仓库下载到本地仓库中尚不存在的更改,但不会自动合并或修改您的当前工作。git fetch
后,您的本地仓库将包含远程仓库的最新更改,但这些更改不会影响您的任何工作分支,除非您显式合并它们。FETCH_HEAD
是一个特殊的引用,它指向刚刚从远程仓库获取的最新提交。git pull
git pull
是 git fetch
和 git merge
的组合。它不仅下载最新的远程更改,还会尝试将这些更改合并到当前分支中。(1)使用 git fetch
检查远程更改
假设您正在本地的 master
分支上工作,并想查看远程仓库(如 origin
)中的更新,但不立即合并这些更改:
git fetch origin
执行此命令后,您可以使用以下命令检查远程分支的状态而不影响您的本地分支:
git log --oneline master..origin/master
这会显示从远程 master
分支获取的提交,这些提交还没有被合并到您的本地 master
分支。
(2) 合并 FETCH_HEAD
如果您决定要将这些更改合并到您的本地分支,可以使用:
git merge FETCH_HEAD
这会将从 git fetch
获取的更改合并到您当前的分支中。
(3)使用 git pull
直接更新和合并
如果您确定要立即获取并合并远程分支的更改,可以直接使用:
git pull origin master
这条命令等同于先执行 git fetch origin master
然后执行 git merge origin/master
。
在将本地分支推送到远程存储库之前,所有提交都可用。换句话说,您可以按照自己的节奏在本地分支工作,而不会影响其他团队成员。
当您将本地分支推送到远程时,Git 将快进合并到目标存储库。
但是,如果推送导致非快进合并,Git 将拒绝您的推送以防止您覆盖以前的提交。在这种情况下,您必须拉取最新的远程更改并再次推送。
在成功的Git分支模型中,提到的五种分支类型,每种都具有特定的作用和管理规则。这些分支类型协助团队在不同的开发阶段进行组织和管理,确保软件开发流程的清晰性和效率。以下是对这些分支的概述和整理:
master
或 main
develop
)分出,进行最后的测试和微调。develop
这些分支策略提供了清晰的结构框架,帮助团队高效管理复杂的开发流程,优化协作和交付速度。根据项目和组织的需求,团队可以对这些策略进行调整,以最适合自己的工作方式。
在存储库中进行第一次提交时,默认情况下 Git 会自动创建一个主分支。随后的提交将在主分支下进行,直到您决定创建并切换到另一个分支。
驻留在主分支的代码库是生产就绪的。当最新的提交准备好用于特定版本时,它将被赋予一个发布标签。
当您开始处理新功能或 bug 修复时,您应该创建一个功能分支 (即主题分支)。功能分支通常是在开发分支之外创建的。在功能的整个开发生命周期中,该主题分支可以驻留在您的本地机器中。
每当您准备好将变更集与开发分支合并时,您将把这个分支推送到远程存储库。
当您推出新版本时,您会创建一个发布分支。发布分支可帮助您确保新功能的正常运行。
按照惯例,在命名发布分支时以前缀release-
开头。
通常当它接近生产就绪时,您会在开发分支之外创建发布分支。
团队成员应仅解决此分支上的 bug 修复和与发布相关的问题。这允许其他团队成员继续将新功能推送到开发分支,而不会中断发布的工作流程。
准备发布时,将发布分支与主分支合并,并为新创建的合并提交标记发布编号。
您还应该将发布分支与开发分支合并,以便主分支和开发分支都可从发布分支接收最新的更改/bug 修复。
当您需要快速向生产代码库添加关键修复时,您可以在主分支之外创建一个修补分支。
按照惯例,在命名修补分支时以前缀hotfix-
开头。
修补分支的优点是它允许您快速发布补丁,并将更改与主分支合并,而无需等待下一个版本。
修补分支也应该与开发分支合并。
您的团队应该始终保持开发分支 (即集成分支) 的稳定。您的团队从这个分支创建新的分支,它可以在生产环境中运行。持续集成工具,例如 Jenkins 可以做到这一点。
当一些更改需要合并到开发分支时,创建一个功能/分支来处理通常是个好主意。
在这个Git分支策略工作流程示例中,我们通过处理一个实际场景来阐明如何在开发新功能的同时快速响应并修复生产中的bug。这种分支策略有效地结合了开发/集成分支和功能/主题分支的使用,确保开发流程的连续性和灵活性。
develop
)分出一个新的分支来专门处理这个bug。这保证了bug修复工作与功能开发工作的隔离。为了使您的修订历史记录保持简洁,您可以在将功能分支合并到开发分支之前,将功能分支变基。这会导致快进合并,而不会创建额外的合并提交。
您可以使用 git merge 指令来将多个分支集成。
考虑下面的情况。有两个分支:一个bugfix
分支,其中有一些来自main
分支的提交。
在这种情况下,将“bugfix“合并回“主要“分支并不是什么大问题。那是因为自从创建“bugfix”分支以来,“主要“分支没有改变。Git 将通过将“主要“分支位置移动到“bugfix“分支的最新位置来合并它。这种合并称为“快进“。
然而,在下面的示例中,自从bugfix
分支出来后,main
分支已经更新了几次。在这两个分支上执行合并时,必须组合来自bugfix
和main
分支的更改。
对于这种合并,创建一个“合并提交“并将“主要“位置更新为新创建的合并提交。
即使快进合并是可能的,您仍然可以明确地强制它在没有快进合并的情况下进行合并。
如上所示,非快进合并保留了bugfix
分支。这让您更清楚地了解功能分支bugfix
。您可以轻松找到功能分支的开始或结束位置,并跟踪对功能分支所做的更改。
要获得更清晰的修订历史记录,您可以使用 git rebase 命令来整合您的分支。
假设我们有两个具有非快进合并场景的分支。
变基将导致分支历史记录看起来类似于下面的示例。
当您将bugfix
分支变基到主分支时,来自bugfix
分支的提交将被重播并附加到主分支的末尾。结果是bugfix
分支历史记录中的单个简单提交串流。
如果在附加提交时发生冲突,Git 会要求您解决冲突,然后再继续对其他提交进行变基。
变基不会移动main
的位置。在任何情况下,您都可以在变基后进行快进或从bugfix
到main
的干净合并。
Git 标签标记并标记历史记录中的特定提交。标签通常用于指示发布版本,发布名称 (即 v1.0) 是标签的名称。
Git 标签有两种类型:
轻量标签类似于不会改变的分支。它只是直接指向历史记录中的特定提交。轻量标签主要在您的本地工作区中暂时使用。
附注标签是校验和的,通常在计划标记重要提交时使用。您可以添加消息、签名、日期以及标记者的姓名和电子邮件。
(1)git diff
用途:git diff
命令用于显示工作目录中未暂存的文件修改和暂存的文件修改之间的差异,或比较两个提交之间的差异。
功能详解:
未暂存的变更:git diff
默认显示工作目录中所有未暂存的变更。
git diff
暂存的变更:使用 git diff --staged
或 git diff --cached
查看已暂存的变更。
git diff --staged
两个提交之间的差异:指定两个提交的哈希值来查看它们之间的差异。
git diff commit1 commit2
(2)git show
用途:git show
命令用于显示一个对象(通常是提交)的类型、大小、内容等信息。
功能详解:
查看特定提交:显示单个提交的详细信息,包括提交的差异和元数据。
git show [commit-hash]
(3)git log
用途:git log
命令用于查看提交历史记录,可以与不同的选项组合使用,以查看特定的历史变更。
功能详解:
查看特定文件的提交历史:显示指定文件的提交历史,包括相关的更改。
git log -p [filename]
图形化显示分支合并历史:使用图形选项查看更直观的分支历史。
git log --graph --oneline --all
(4)git blame
用途:git blame
命令用于显示每一行文件的最后修改者信息,非常有用于追踪特定行的变更历史。
功能详解:
查看文件修改者:逐行显示文件的修改记录,包括提交哈希和作者。
git blame [filename]
git status
和 git log
是两个基本的 Git 命令,它们在日常 Git 使用中扮演着不同的角色。这两个命令提供的信息有着根本的区别,分别关注当前工作区的状态和项目的提交历史。
用途:git status
命令用于显示 Git 工作目录和暂存区的状态。它是诊断和解决代码中状态相关问题的首选工具。
主要功能:
输出示例:
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: example.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
sample.txt
用途:git log
命令用于显示当前分支的提交历史。它可以帮助开发者回顾和审查项目的发展过程。
主要功能:
--graph
选项展示分支合并历史。输出示例:
commit fa3e98197e714dbf123681f6927a05538db6aa56 (HEAD -> main, origin/main, origin/HEAD)
Author: John Doe <john@example.com>
Date: Wed Sep 15 14:56:29 2021 +0200
Add new feature
commit aea57694cd1bfeda98234aeccc8ae202b58db2b4
Author: Jane Smith <jane@example.com>
Date: Tue Sep 14 12:48:53 2021 +0200
Update README.md
这两个命令在日常的 Git 使用中非常关键,为开发者提供了关于项目状态和历史的重要信息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。