我正在做一个web应用程序,我需要为一些主要的更改做一个分支,事情是,这些更改需要更改数据库模式,所以我想把整个数据库放在git下。

我怎么做呢?是否有一个特定的文件夹,我可以保存在git存储库下?我怎么知道是哪个?我如何确定我放入了正确的文件夹?

我需要确定,因为这些更改是不向后兼容的;我可不能搞砸。

在我的例子中,数据库是PostgreSQL

编辑:

有人建议进行备份并将备份文件置于版本控制之下,而不是将数据库置于版本控制之下。说实话,我觉得这真的很难接受。

肯定有更好的办法。

更新:

好吧,没有更好的方法了,但我还是不太相信,所以我要稍微改变一下问题:

我想将整个数据库置于版本控制之下,我可以使用什么数据库引擎来将实际数据库置于版本控制之下,而不是转储?

sqlite是git友好的吗?

因为这只是开发环境,所以我可以选择任何我想要的数据库。

Edit2:

我真正想要的不是跟踪我的开发历史,而是能够从我的“新的根本性变化”分支切换到“当前稳定的分支”,并且能够用当前稳定的分支修复一些错误/问题等。这样,当我切换分支时,数据库就会自动地与我当前所在的分支兼容。 我不太关心实际数据。


当前回答

以下是我在项目中尝试做的事情:

分离数据、模式和默认数据。

数据库配置存储在不受版本控制的配置文件中(.gitignore)

数据库默认值(用于设置新项目)是一个受版本控制的简单SQL文件。

对于数据库模式,在版本控制下创建数据库模式转储。

最常见的方法是使用包含SQL语句的更新脚本(ALTER Table..或更新)。你还需要在你的数据库中有一个地方来保存你的模式的当前版本)

看看其他大型开源数据库项目(piwik,或者你最喜欢的cms系统),它们都使用updatescripts (1.sql,2.sql,3.sh,4.php.5.sql)

但这是一项非常耗时的工作,您必须创建并测试更新脚本,还需要运行一个通用的更新脚本来比较版本并运行所有必要的更新脚本。

所以理论上(这就是我正在寻找的)你可以 在每次更改后转储数据库模式(手动,conjob, git钩子(可能在提交之前)) (只有在一些非常特殊的情况下才创建更新脚本)

之后,在您的普通updatescript中(对于特殊情况,运行正常的updatescript),然后比较模式(转储和当前数据库),然后自动生成必要的ALTER语句。已经有一些工具可以做到这一点,但还没有找到一个好的工具。

其他回答

我开始想一个非常简单的解决方案,不知道为什么我以前没有想到!!

复制数据库(包括模式和数据)。 在new-major-changes的分支中,只需更改项目配置以使用新的重复数据库。

这样我就可以切换分支,而不用担心数据库模式更改。

编辑:

复制,我的意思是用不同的名称创建另一个数据库(如my_db_2);不是去倾倒之类的东西。

我遇到过这个问题,因为我有一个类似的问题,其中一些近似于基于DB的目录结构,存储“文件”,我需要git来管理它。它是分布式的,在云上使用复制,因此它的接入点将通过MySQL。

上述答案的要点,似乎类似地提出了一个问题的替代解决方案,使用Git来管理数据库中的一些东西,这有点错过了重点,所以我将尝试回答这个问题。

Git是一个系统,它在本质上存储了一个增量(差异)数据库,可以对其进行重新组装,以重现上下文。git的正常使用假设上下文是一个文件系统,而那些增量是该文件系统中的diff,但实际上所有git都是一个增量的分层数据库(分层,因为在大多数情况下,每个增量都是一个至少有一个父级的提交,以树状排列)。

理论上,只要你能生成一个增量,git就可以存储它。问题是git通常期望它生成delta的上下文是一个文件系统,类似地,当您签出git层次结构中的一个点时,它期望生成一个文件系统。

If you want to manage change, in a database, you have 2 discrete problems, and I would address them separately (if I were you). The first is schema, the second is data (although in your question, you state data isn't something you're concerned about). A problem I had in the past, was a Dev and Prod database, where Dev could take incremental changes to the schema, and those changes had to be documented in CVS, and propogated to live, along with additions to one of several 'static' tables. We did that by having a 3rd database, called Cruise, which contained only the static data. At any point the schema from Dev and Cruise could be compared, and we had a script to take the diff of those 2 files and produce an SQL file containing ALTER statements, to apply it. Similarly any new data, could be distilled to an SQL file containing INSERT commands. As long as fields and tables are only added, and never deleted, the process could automate generating the SQL statements to apply the delta.

The mechanism by which git generates deltas is diff and the mechanism by which it combines 1 or more deltas with a file, is called merge. If you can come up with a method for diffing and merging from a different context, git should work, but as has been discussed you may prefer a tool that does that for you. My first thought towards solving that is this https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#External-Merge-and-Diff-Tools which details how to replace git's internal diff and merge tool. I'll update this answer, as I come up with a better solution to the problem, but in my case I expect to only have to manage data changes, in-so-far-as a DB based filestore may change, so my solution may not be exactly what you need.

以下是我在项目中尝试做的事情:

分离数据、模式和默认数据。

数据库配置存储在不受版本控制的配置文件中(.gitignore)

数据库默认值(用于设置新项目)是一个受版本控制的简单SQL文件。

对于数据库模式,在版本控制下创建数据库模式转储。

最常见的方法是使用包含SQL语句的更新脚本(ALTER Table..或更新)。你还需要在你的数据库中有一个地方来保存你的模式的当前版本)

看看其他大型开源数据库项目(piwik,或者你最喜欢的cms系统),它们都使用updatescripts (1.sql,2.sql,3.sh,4.php.5.sql)

但这是一项非常耗时的工作,您必须创建并测试更新脚本,还需要运行一个通用的更新脚本来比较版本并运行所有必要的更新脚本。

所以理论上(这就是我正在寻找的)你可以 在每次更改后转储数据库模式(手动,conjob, git钩子(可能在提交之前)) (只有在一些非常特殊的情况下才创建更新脚本)

之后,在您的普通updatescript中(对于特殊情况,运行正常的updatescript),然后比较模式(转储和当前数据库),然后自动生成必要的ALTER语句。已经有一些工具可以做到这一点,但还没有找到一个好的工具。

我推荐neXtep(链接被删除-域名被nsfw网站接管)来控制数据库的版本,它有一组很好的文档和论坛,解释了如何安装和遇到的错误。我已经对postgreSQL 9.1和9.3进行了测试,我能够让它在9.1中工作,但在9.3中似乎无法工作。

这个问题基本上已经回答了,但我想用一个小建议来补充X-Istence和Dana the Sane的回答。

如果您需要具有一定粒度的修订控制,比如每天,那么您可以使用rdiff-backup之类的工具将表和模式的文本转储与增量备份结合起来。这样做的好处是,不存储每日备份的快照,而只存储与前一天的差异。

这样你就有了修订控制的优势,也不会浪费太多的空间。

在任何情况下,直接在频繁更改的大平面文件上使用git都不是一个好的解决方案。如果数据库变得太大,git在管理文件时会出现一些问题。