如何在Git中实现部署分支

22

我在一个PHP项目中使用git,我认为它非常方便。但有一件事情如果能实现就更好了。

我创建了一个用于部署的分支。它具有一些不同之处,例如不同的配置文件和文档。

我不能简单地忽略它们,因为那样它们将保留在两个分支中,而我希望在两个分支中保持它们的不同。

问题是当我合并这些分支时,那些要求不同的文件也会被合并。

有没有什么方便的方法来实现这个目标?通常怎么做呢?

12个回答

12

2021年2月更新:Git本身仍不适合,但GitHub Action环境可能有所帮助

2009年: 我不确定Git是否应该以这种方式使用。

首先快速提供一下Linus的建议,总是“丰富多彩”的和有信息量的;)

Git非常根本地跟踪项目状态,而不是文件状态。 这意味着您不能尝试“合并文件”。 在Git中这是没有意义的操作。 实际上,在任何允许此操作的SCM中都注定会成为一个彻底的**东西。

(*)我之所以这么说,并不仅仅是因为Git无法做到这一点。 它比那更根本。 一旦您开始对每个文件进行分支和合并,基本上就已经把自己搞砸了,而且您将永远无法再像“整个项目”一样工作 - 您不再具有实际上是整个项目历史记录的明确定义的历史记录。


好了。

话虽如此,您可以:

  • 将这些config/doc文件管理为单独的git子项目(注意:此处已经讨论了使用子模块
  • 或记录部分合并(对于我们不想合并的文件,使用“ours”战略),然后--amend它。

此线程中的其他解决方案涉及在部署服务器上的“特定于服务器”的分支上工作。

Development        Deployment

#origin/master:
x--x               $ git clone

                   # master
                   x--x

                   $ git checkout -b deployment origin/master

                   x--x
                       \ 
                        -- #deployment

                   $ .... #makes changes for config files
                          #or other specific deployment files

                   x--x
                       \
                        --d1--d2 # no need to push that branch ever.

#new developments
x--x--x--x

                   $ git pull --rebase #pull origin/master and 
                                       #replay current branch on top of it
                   x--x--x--x
                             \
                              --d1'--d2' #SHA1 rewritten in deployment branch
                                         #not important since this branch 
                                         #is not pushed (published)
         
              

5

我会一些小技巧,例如:

  • 让应用程序读取文件config
  • 添加config.developmentconfig.production,但不将config添加到存储库中
  • 让您的部署脚本不仅克隆存储库,还要执行cp config.production config

这有意义吗?

对我来说是可以的。


1
我没有真正的部署脚本,但是我已经解决了这个问题,制作了一个config.template.php和一个config.php文件,然后让git忽略config.php文件。 - Ikke

5

这对我有效,我只需进行少量配置更改即可部署(在配置文件中修改3行)。

  1. 从GitHub或其他存储库克隆您的代码库,并将其部署到您想要的位置。

  2. 运行git checkout -b deployment origin/master

  3. 进行更改(如果需要,可以推送更改)。

  4. 每当您的主分支(或您从中进行部署的任何其他分支)有您要部署的更改时,只需运行git pull --rebase

这是一个简单的解决方案,对我非常有效,但我不能确定它是否像其他人所说的那样“糟糕”,但对于我们的目的来说确实非常有用。


2
想了想,我建议避免这样做,因为这样做过于复杂。相反,在您的.conf文件中使用SetEvn设置影响/确定配置的环境变量。例如,在我的开发服务器上,我的站点的DATABASE_URL ='mysql:root@localhost / bla',在生产环境中它可能是DATABASE_URL ='mysql:app @ localhost / appdb'。 - arbales

3

简短回答是,永远不要合并分支。事实上,你根本不需要合并它们,只需从开发(也称“主”)合并到部署以合并修复和通用更改。


2
我真的不太明白。不要合并,但只是合并。你是指单向合并吗? - Ikke
我认为他的意思是:将部署特定文件保存在B分支中,将本地配置文件保存在A分支中,在主分支中进行开发。从主分支合并到A进行测试,从主分支合并到B进行部署;永远不要从A或B合并到主分支。 - Paul
准确地说:我的意思是,不要将分支合并在一起,而是在分支之间合并单个变更集。 - Keltia

2
如果您想保持历史记录的整洁,可以将部署文件保存在干净分支的一些提交中。然后,在需要部署新版本时,您可以检出部署分支并使用“git rebase master”命令,将这些提交放在原始分支的顶部。
这样,您还可以轻松更改配置文件,并使用“git commit --amend”命令更改顶部提交。

1

cherry-pick 看起来对此很有效(代价是有点污染日志)。

git checkout -b testing 进行更改并提交 git checkout master git checkout -b deploy 进行更改并提交 git checkout master

在主分支下完成所有操作, 使用 git cherry-pick testing 或 git cherry-pick deploy 应用所需的差异,以从当前系统切换到测试或部署版本。


1

我之前提到过补丁文件。现在我不再使用它们,而是维护部署分支。

也就是说,我从主分支(master)创建一个名为“master-deployed”的新分支,并在该分支上进行更改,这些更改仅需要在构建服务器上的测试版本中(例如,在web.config中添加警告,说明这不是实时版本,并且使用了不同的数据库服务器)。

当构建 bleeding edge 版本时,构建服务器会检出 master-deployed 分支,并在执行常规构建之前将其 rebase 到 origin/master。如果没有人做出任何冲突的更改,那么一切都很好。如果有,则我无法看到任何系统可以在没有手动干预的情况下处理此问题。

qa 的顶端也是如此,它有一个名为“qa-deployed”的分支。

我使用 --onto 标志来确保如果整个分支被重写,则补丁不会带走所有旧提交。

因此,在构建服务器上,qa 构建看起来像:

git reset --hard
git clean -xfd
git checkout -f qa-deployed
git rebase --onto qa HEAD^ qa-deployed
build-script

1

我曾经遇到过类似的问题,于是创建了一个名为config-magic的小项目来帮助管理这个问题。

Config-magic允许您创建模板配置文件,然后为每个开发/暂存/生产环境创建数据配置文件。然后运行“cfg dev”生成“dev”配置文件,“cfg staging”生成暂存配置文件等。

然后我将其与脚本连接起来,这样当我部署到暂存环境时,我会在本地运行“cfg staging”,然后从git更新代码库后,将所有配置文件scp过去。

“实际”的配置文件被设置为被git忽略。到目前为止,这对我非常有效。

https://github.com/apinstein/config-magic/tree


1
我在考虑我的情况下所有这些解决方案,但似乎都不适用。我在我的实时和开发服务器上进行编辑。如果您不需要重新发布该分支,则Rebase效果很好,但我会在部署分支上进行更改,并将其发布回主存储库。子模块方式仅在文件位于单独的子目录中时才有效,而我的配置文件位于几个位置。合并我们的方法也不太适用,因为我必须先拉取那个分支,然后再拉取大分支。也许如果仍然有一个合并他们的方法,当需要时我可以拉取正确的配置分支。现在,.gitignore可以工作,我只需手动上传文件即可。
经过更多的研究,我找到了解决方案,即不在实时站点上拥有git repo,而是使用暂存站点将最新更改拉入我的带有暂存/实时配置文件的分支中,然后通过git archive部署并提取文件到我的实时站点。

0

目前我有几个补丁文件已经提交了,并且构建服务器会为相关版本应用这些补丁。尽管此刻我有些犹豫。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接