在 git 中跨分支创建永久不同的更改
Creating permanently differing changes across branches in git
这个问题具体涉及 git 和 GoogleAppEngine 的使用,但它的答案可能对拥有针对不同环境的分支的任何人都有用。
我们发现合并过程中不需要的代码持续交叉污染分支的问题。
一些背景:我们正在使用 git 来管理上传到 GoogleAppEngine 的代码。我们有 3 个主要分支(master、staging 和 development),每个分支都有自己独立的 GAE 项目。部署到 GAE 的标准方法是通过 Gradle 插件,它使用单个 xml 配置文件(目录层次结构中的固定名称和固定位置)来指定目标 GAE 项目和版本号。
例如
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>projectname-development</application>
<version>307</version>
<threadsafe>true</threadsafe>
</appengine-web-app>
因此,此文件已在每个分支上进行了修改,以便为 <application>
标记添加正确的 -live
和 -staging
后缀。
我们的工作流程很复杂,但并不罕见。新功能从开发分支并合并回开发(--no-ff 所以我们可以看到分支历史)。然后将开发合并到暂存中。 Staging 合并到 master 中。暂存的错误修复被分支到一个错误修复分支,然后合并回暂存并返回到开发。
当我们开始在主要分支之间合并或对开发分支进行错误修复时,我们的问题就出现了。 git 大多数时候通过替换 XML 中的 GAE 目标项目来解决合并问题。我可以在第一次合并时理解这一点(因为这是它变得不同的地方),但是我们使用 --no-ff 和 --no-commit 执行合并所以我们可以正确更新版本号(因为它们作为一部分递增我们的合并政策)和 git 似乎在每次使用合并时都试图合并不正确的内容。
这个问题的'psuedocode'如下:-
创建初始分支...
1. 将 xml 文件提交给 master.
2.分支大师到开发
3. 更改 xml in development 和 commit
中的 GAE 目标项目
开发功能...
4.从development创建feature分支,make feature,增加版本号,合并回development
5. 合并开发以掌握 --no-ff 和 --no-commit
此时,正如预期的那样,它会将GAE目标项目和版本从开发合并到主版本。我们手动将 GAE 目标项目更正为它在 master 分支上的内容,但保留对版本号的更改;并提交。
开发另一个功能...
6.从development创建feature分支,make feature,增加版本号,合并回development
7. 合并开发以掌握 --no-ff 和 --no-commit
在这一点上,事情并不像预期的那样。 Git 已更改版本号 和 GAE 目标项目 。如果不尝试,我 99.9% 确定其他源代码控制(根据我的经验,SVN、Vault 或 Perforce)只会合并版本号,这是我在这里期望的结果。
我们最初没有注意到这个问题,因为 SourceTree 对我们隐藏了更改(根本没有显示在日志中?!)。只有在从命令行执行此操作并查看沿途的每一步时,我们才注意到问题出在哪里。这几乎就像 git 太聪明了,它认为我们没有提交那个大块头(因为我们在提交之前手动编辑了文件)我们已经做了某种樱桃挑选并且它试图做一个延迟稍后合并。
所以,我的问题是 "How do we tell git that when we have committed our merged file from branch B to branch A, that we have taken all the changes from it we want?",或者有 better/different 解决这个问题的方法吗?
It's almost like git is being too clever and it's figuring that as we've not committed that hunk (because we manually edited the file before commit) that we have done some sort of cherry pick and it tries to do a deferred merge at a later stage.
这不可能。 Git 仅跟踪已提交内容的快照。它不关心你是如何或为什么走到那一步的。
我试过你的例子,但我只遇到连续行冲突时的问题,即版本号在 dev 中更改,应用程序名称在 dev 和 master 之间不同。在这种情况下,我遇到了冲突,但这是预料之中的,因为 Git 注意到更改后的行并没有完全适合目标分支中的上下文,否则与原始分支匹配。
但是,当版本号与应用程序名称分开 4 行时我没有遇到任何问题,只有版本号受到影响,而不是应用程序名称。
无论如何,在程序文件中存储临时信息可能不是一个好主意。最好将版本号和应用程序名称保存在永远不会提交的 属性 文件中,然后有一个快速更新脚本读取 属性 文件以设置 XML 文件拥有正确的价值观。更好的是,大多数工具允许您根据 属性 文件声明变量。尝试调查您的构建工具是否支持它。
编辑:
版本号可能是必需的,但不应在任何分支上提交应用程序名称。相反,使用占位符和结帐挂钩或 .gitattributes
过滤器,它将根据当前分支将占位符替换为适当的应用程序名称。
有关详细信息,请参阅
http://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
和
http://git-scm.com/docs/gitattributes
这个问题具体涉及 git 和 GoogleAppEngine 的使用,但它的答案可能对拥有针对不同环境的分支的任何人都有用。
我们发现合并过程中不需要的代码持续交叉污染分支的问题。
一些背景:我们正在使用 git 来管理上传到 GoogleAppEngine 的代码。我们有 3 个主要分支(master、staging 和 development),每个分支都有自己独立的 GAE 项目。部署到 GAE 的标准方法是通过 Gradle 插件,它使用单个 xml 配置文件(目录层次结构中的固定名称和固定位置)来指定目标 GAE 项目和版本号。
例如
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>projectname-development</application>
<version>307</version>
<threadsafe>true</threadsafe>
</appengine-web-app>
因此,此文件已在每个分支上进行了修改,以便为 <application>
标记添加正确的 -live
和 -staging
后缀。
我们的工作流程很复杂,但并不罕见。新功能从开发分支并合并回开发(--no-ff 所以我们可以看到分支历史)。然后将开发合并到暂存中。 Staging 合并到 master 中。暂存的错误修复被分支到一个错误修复分支,然后合并回暂存并返回到开发。
当我们开始在主要分支之间合并或对开发分支进行错误修复时,我们的问题就出现了。 git 大多数时候通过替换 XML 中的 GAE 目标项目来解决合并问题。我可以在第一次合并时理解这一点(因为这是它变得不同的地方),但是我们使用 --no-ff 和 --no-commit 执行合并所以我们可以正确更新版本号(因为它们作为一部分递增我们的合并政策)和 git 似乎在每次使用合并时都试图合并不正确的内容。
这个问题的'psuedocode'如下:-
创建初始分支...
1. 将 xml 文件提交给 master.
2.分支大师到开发
3. 更改 xml in development 和 commit
开发功能...
4.从development创建feature分支,make feature,增加版本号,合并回development
5. 合并开发以掌握 --no-ff 和 --no-commit
此时,正如预期的那样,它会将GAE目标项目和版本从开发合并到主版本。我们手动将 GAE 目标项目更正为它在 master 分支上的内容,但保留对版本号的更改;并提交。
开发另一个功能...
6.从development创建feature分支,make feature,增加版本号,合并回development
7. 合并开发以掌握 --no-ff 和 --no-commit
在这一点上,事情并不像预期的那样。 Git 已更改版本号 和 GAE 目标项目 。如果不尝试,我 99.9% 确定其他源代码控制(根据我的经验,SVN、Vault 或 Perforce)只会合并版本号,这是我在这里期望的结果。
我们最初没有注意到这个问题,因为 SourceTree 对我们隐藏了更改(根本没有显示在日志中?!)。只有在从命令行执行此操作并查看沿途的每一步时,我们才注意到问题出在哪里。这几乎就像 git 太聪明了,它认为我们没有提交那个大块头(因为我们在提交之前手动编辑了文件)我们已经做了某种樱桃挑选并且它试图做一个延迟稍后合并。
所以,我的问题是 "How do we tell git that when we have committed our merged file from branch B to branch A, that we have taken all the changes from it we want?",或者有 better/different 解决这个问题的方法吗?
It's almost like git is being too clever and it's figuring that as we've not committed that hunk (because we manually edited the file before commit) that we have done some sort of cherry pick and it tries to do a deferred merge at a later stage.
这不可能。 Git 仅跟踪已提交内容的快照。它不关心你是如何或为什么走到那一步的。
我试过你的例子,但我只遇到连续行冲突时的问题,即版本号在 dev 中更改,应用程序名称在 dev 和 master 之间不同。在这种情况下,我遇到了冲突,但这是预料之中的,因为 Git 注意到更改后的行并没有完全适合目标分支中的上下文,否则与原始分支匹配。
但是,当版本号与应用程序名称分开 4 行时我没有遇到任何问题,只有版本号受到影响,而不是应用程序名称。
无论如何,在程序文件中存储临时信息可能不是一个好主意。最好将版本号和应用程序名称保存在永远不会提交的 属性 文件中,然后有一个快速更新脚本读取 属性 文件以设置 XML 文件拥有正确的价值观。更好的是,大多数工具允许您根据 属性 文件声明变量。尝试调查您的构建工具是否支持它。
编辑:
版本号可能是必需的,但不应在任何分支上提交应用程序名称。相反,使用占位符和结帐挂钩或 .gitattributes
过滤器,它将根据当前分支将占位符替换为适当的应用程序名称。
有关详细信息,请参阅 http://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks 和 http://git-scm.com/docs/gitattributes