gpt4 book ai didi

git - Git子树 merge 策略或子树命令?

转载 作者:行者123 更新时间:2023-12-03 01:28:25 24 4
gpt4 key购买 nike

我正在启动一个新的Zend Framework项目,在其中我将与设计师合作。我将使用git来维护该项目代码,通常设计人员不会讲git(或任何编程语言),所以我想让他轻松一点,否则我怕他根本不会使用git。我的计划是给他一些Git gui,并且他应该只使用基本的git功能,例如commit,diff,fetch,merge,push和pull。

我正在使用gitolite来维护git存储库的共享副本,并且由于它具有精细的权限系统,因此我将仅为专用分支(设计)提供给设计师RW访问权限,并对其他分支进行读取访问。

为了简单起见,我只想与他共享主项目中某些文件夹(ZF recommended structure之后),而他确实需要访问这些文件夹才能完成其工作。同时,我希望我们俩仍然可以彼此合并。

他分支的简化结构应为:

<project name>/
application/
layouts/
scripts/
views/
scripts/
public/
css/
images/
js/


我知道我可以使用子模块来执行此任务,但是维护起来会很痛苦,因为我应该将我的项目划分为(至少)4个子存储库,他应该只能访问子存储库,并且他将有3个存储库可以使用。因此,如果这是唯一的解决方案,我将放弃这个想法。

我已经阅读了一些链接,这些链接使我认为我的要求是可能的:


git subtree command
git subtree merge strategy


这是我的问题:


如何创建精简分支 designgit checkout -b designgit mv/rm?)
如何配置git以跟踪跨分支的编辑(因此我可以从master分支 git merge design,反之亦然)


更新:

我找到了解决这两个SO问题所给出问题的另一种可能方法


How do I tell git to always select my local version for conflicted merges on a specific file?
How to setup a git driver to ignore a folder on merge


我尝试在design分支中实现 git rm all-unneeded-stuff之后的第一个,我在master分支中进行了提交,其中涉及白名单路径中的一个文件和黑名单路径中的另一个文件,但是 git merge失败,并显示以下消息

CONFLICT (delete/modify): application/Bootstrap.php deleted in HEAD and modified in master. Version master of application/Bootstrap.php left in tree.


然后,我在master分支中添加了一个新目录,并在与设计合并时添加了新目录。我在驱动程序中放入了一些调试回显,并且发现这两种情况都没有调用它,可能是因为这不是真正的合并。

我还没有尝试过第二种方法(.gitignore方法),但是如果我了解该方法不符合我的需要,因为它只会忽略设计分支中列入黑名单的文件,但是它们会在设计分支,打破了我的要求。

我在 GitHub上进行了实验

更新2:

我认为目前还没有解决方案。使用当前的git实现,这是根本无法实现的。

我很想矛盾,但是我担心这不会发生。

最佳答案

听起来您希望能够限制每个目录的读取访问权限。这是可能的,但是我知道的唯一解决方案远非简单。它涉及服务器上同一存储库的多个版本,每个版本都使用一些复杂的钩子魔术来同步以过滤出子目录。

我正在努力在业余时间实现钩子,最终目标是将其作为开源软件发布(也许是对gitolite的一项功能添加),但不幸的是我的业余时间有限。

储存库

通用解决方案涉及同一存储库的至少三个变体:一个授权存储库,用于协调两个或多个委托存储库。用户从不克隆权限存储库。仅委托存储库被克隆。

委托负责将传入的提交转发到授权存储库。权限存储库负责为每个其他委托存储库适当地过滤传入的提交。然后将结果下推给其他代表。

权限存储库不是严格要求的-代表可以自己执行过滤,然后将结果直接推送给其他委托人-但是使用另一个存储库作为集中协调器可以大大简化实现。

委托存储库

每个委托存储库都包含整个项目数据的子集(例如,滤除了零个或多个子目录)。所有委托存储库彼此相同,不同之处在于每个委托都有一组不同的文件被过滤掉。它们都具有相同的提交历史记录图,但是提交将具有不同的文件内容,因此具有不同的SHA1标识符。它们具有相同的分支和标记集(换句话说,如果项目具有master分支,则每个委托存储库也具有master分支),但是由于等效提交的SHA1标识符不同,因此引用将指向不同的SHA1标识符。

例如,以下是两个委托存储库内容的图表。 everything.git存储库没有任何内容被过滤掉,但是no-foo.git存储库中的所有子目录foo都被过滤掉了。

$ cd ~git/repositories/everything.git
$ git log --graph --oneline --decorate --date-order --all
* 2faaad9 (HEAD, master) barbaz
| * c3eb6a9 (release) foobar
* | 8b56913 Merge branch 'release'
|\ \
| |/
| * b8f899c qux
* | aad30f1 baz
|/
* f4acd9f put a new file in subdirectory bar
* 2a15586 put a new file in subdirectory foo

$ cd ~git/repositories/no-foo.git
$ git log --graph --oneline --decorate --date-order --all
* 81c2189 (HEAD, master) barbaz
| * 6bbd85f (release) foobar
* | c579c4b Merge branch 'release'
|\ \
| |/
| * 42c45c7 qux
* | 90ecdc7 baz
|/
* 4d1cd8d put a new file in subdirectory bar
* 9cc719d put a new file in subdirectory foo


请注意,这两个图看起来相同,具有相同的提交消息,相同的分支名称等。唯一的区别是SHA1 ID,原因是文件内容不同。

(旁注:提交也可以被过滤掉,以防止其他代表的用户甚至不知道已在过滤出的目录中进行了提交。但是,只有在接触到已过滤的目录中的文件时,该提交才能被过滤掉。 out目录。否则,将存在钩子无法自动解决的合并冲突。)

权限存储库

权限存储库是所有委托权限的超集。每个委托存储库中的所有提交对象都会通过每个委托存储库中的钩子自动推送到权限存储库中。因此,如果有两个委托存储库,则授权存储库中将存在两个同构的DAG(每个委托一个)(假设这些委托不共享公共的根提交)。

权限存储库还将具有来自每个委托人的每个项目分支的版本,并以委托人的名称为前缀。继续上面的示例, everything.git委托存储库有一个指向提交 master2faaad9分支,而委托 no-foo.git有一个指向过滤后但与之等效的提交 master81c2189分支。在这种情况下, authority.git将具有两个主分支: everything/master指向 2faaad9no-foo/master指向 81c2189。下图说明了这一点。

$ cd ~git/repositories/authority.git
$ git log --graph --oneline --decorate --date-order --all
* 2faaad9 (everything/master) barbaz
| * 81c2189 (no-foo/master) barbaz
| | * c3eb6a9 (everything/release) foobar
| | | * 6bbd85f (no-foo/release) foobar
* | | | 8b56913 Merge branch 'release'
|\ \ \ \
| | |/ /
| |/| |
| | * | c579c4b Merge branch 'release'
| | |\ \
| | | |/
| * | | b8f899c qux
| | | * 42c45c7 qux
* | | | aad30f1 baz
|/ / /
| * | 90ecdc7 baz
| |/
* | f4acd9f put a new file in subdirectory bar
| * 4d1cd8d put a new file in subdirectory bar
* | 2a15586 put a new file in subdirectory foo
/
* 9cc719d put a new file in subdirectory foo


请注意,每个提交有两个版本,每个委托一个。还要注意分支名称。

钩子

委托存储库

每个委托提要提交到授权存储库。

当用户更新委托存储库中的引用(通过 git push)时,该存储库的 update挂钩会自动将 git push放入权限存储库中。但是,它没有使用标准的push refspec,而是使用refspec,该refspec使授权存储库中的引用以委托存储库的名称为前缀(例如,如果委托存储库名为 foo.git,则它将使用诸如< cc>和 +refs/heads/master:refs/heads/foo/master)。

权限存储库

权限存储库过滤传入的提交并将其下推到其他委托存储库中。

当委托存储库推入授权存储库时,授权的 +refs/tags/v1.0:refs/tags/foo/v1.0钩子:


检查用户是否正在尝试在过滤出的目录之一中创建文件。如果是这样,它将退出并出现错误(否则可能存在无法自动解决的合并冲突)。
移植回最初被过滤掉的子目录,形成一棵没有被过滤掉的树。
对于每个其他委托,请过滤未过滤的树以进行等效提交,并删除适当的内容。
将等效提交推送到委托存储库。


必须注意避免委托存储库之间出现争用情况,并正确处理错误。

你的情况

在您的示例中,您将有两个这样的委托存储库:


update(为您)
everything.git(适用于您的设计师)


zend-project.git中的分支将以与两个委托存储库相对应的 authority.giteverything为前缀。

当您在 zend-project中推送到 master时,将发生以下情况:


everything.git中的 update钩子会将传入的提交推送到 everything.git中的 everything/master分支。
对于每个传入的提交, authority.git中的 update钩子将:

创建一个新树对象,该树对象与提交的树100%相同,但是删除 authority.gitapplication子目录之外的所有内容。
使用新树和等效的父级创建一个新的提交对象,但是重用原始的提交消息,作者和时间戳。
更新 public指向新的提交。

zend-project/master中的 zend-project/master推入 authority.git中的 master


当您的设计师将 zend-project.git推入 master时,将发生以下情况:


zend-project.git中的 update钩子会将传入的提交推送到 zend-project.git中的 zend-project/master分支。
对于每个传入的提交, authority.git中的 update钩子将:

检查是否在 authority.gitapplication子目录之外创建了任何新文件。如果是这样,请返回一条错误消息。
创建一个新的树对象,该树对象与落实的树100%相同,不同之处在于移植了 public中的其他子目录。
使用新树和等效的父级创建一个新的提交对象,但是重用原始的提交消息,作者和时间戳。
更新 everything/master指向新的提交。

everything/master中的 everything/master推入 authority.git中的 master


笔记

上面描述了一种实现按目录读取访问控制的方法。如果您确实不希望某些用户能够访问存储库的某些部分,那么它应该是合适的。就您而言,为设计人员提供方便可能比限制访问权限更为重要。如果是这样,可能会有一种更简单的方法来完成您想要的。

我希望我能够足够清楚地解释这一点。

关于git - Git子树 merge 策略或子树命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6588997/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com