V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
AndyAO
V2EX  ›  问与答

如何在 git add . 的时候忽略嵌套的 Git 仓库(embedded git repository)?

  •  2
     
  •   AndyAO · 2021-05-31 15:10:11 +08:00 · 1017 次点击
    这是一个创建于 1298 天前的主题,其中的信息可能已经有所发展或是发生改变。

    正在管理的 Git 仓库中有很多嵌套的 Git 仓库(embedded git repository),这些仓库事实上是代码的中间产物,它们被创建在代码文件的根目录下,但并不打算将它们纳入版本控制当中,因为这些是自动化的产物,真正需要管理的是生成它们的代码。

    在 Sourcetree 中这种嵌套的仓库是被直接忽略的,但 Git 命令行默认好像不是这样,当 git add . 的时候会将其作为子模块提交到暂存区,这并不是我想要的行为。

    所以想找到某种方式,让 git add . 命令,自动的忽略那些嵌套的 Git 仓库。

    猜测 Sourcetree 之所以是自动忽略的,很可能使用了某种特殊的配置文件,但在查看了 git config 的相关文档之后,我好像并没有找到这样的内容。

    那么该如何实现这个需求呢?

    更多内容

    1. 那些中间产物并不能用完就立即删除,因为有的时候还会进行交互式的操作。
    2. 使用 ignore 来手动忽略那些仓库是可行的,这会付出不必要的额外劳动,所以最好的方式还是类似于 Sourcetree 那样,git add . 根本就不会自动的将嵌套的仓库转换为子仓库并纳入跟踪。
    3. 将中间文件统一放在某个特定的文件夹中,然后 ignore 它,这也是可行的,但是当我想手动操作那些仓库的时候,由于它们和代码离得太远了,不在相同的文件夹中,所以会带来额外的麻烦。
    第 1 条附言  ·  2021-06-01 09:43:07 +08:00
    在 Git 邮件列表中问了这个问题,想找到关闭这个机制的方法,但 Junio C Hamano 回复了我,没有提到怎么关闭,只是说使用忽略机制,看样子好像没有办法关闭这个机制。

    原文如下

    You can use the ignore mechanism to exclude it and "git add ." would
    not touch it.

    In my checkout of the git repository, I have a separate copy of the
    same git repository and checked out at the path "Meta/". In the
    upper-level repository, I have "/Meta" in .git/info/exclude (among
    other private-ignore patterns), and that would keep it out of the
    main repository's index even with "git add ." (not that I'd ever use
    "add everything", which I do not think have any place in my
    workflow). This is done without using .gitignore because it is
    nobody else's business that I use such a "strange" setup and use the
    pathname "Meta/" for it (hence project participants do not have to
    know about it).
    6 条回复    2021-06-04 08:28:25 +08:00
    momocraft
        1
    momocraft  
       2021-05-31 15:18:37 +08:00
    你说的"嵌套的 Git 仓库" 在文件系统上是什么样子的

    我记得 git cli 已经默认忽略不被自己管理 (不是 submodule 或 worktree) 的 repository (内有.git) 了
    AndyAO
        2
    AndyAO  
    OP
       2021-05-31 15:38:16 +08:00
    @momocraft #1

    目录的具体结构如下:

    忽略子模块_ignore_submodules
    ├──repo
    │ ├──.git
    │ └──embedded_repo
    │ └──.git
    ├──main.Tests.ps1
    └──README.md

    在这种状态下运行 git status -s 的结果是 ?? embedded_repo/,只看到了这个仓库本身里面的内容隐藏了。

    如果 git add . 然后 git commit -m 'add embedded_repo,你就会发现这东西已经被作为「子模块」添加进去了,git show 会得到关于这个 Subproject 的如下信息

    commit cd14f6e7bffe8081d5bf64928827e3b3a7fe7026
    Author: fibo
    Date: Mon May 31 15:37:41 2021 +0800

    add embedded_repo

    diff --git a/embedded_repo b/embedded_repo
    new file mode 160000
    index 0000000..6e9991c
    --- /dev/null
    +++ b/embedded_repo
    @@ -0,0 +1 @@
    +Subproject commit 6e9991c95f5ca92fdcca22e3ca1cfd54a47343e1
    AndyAO
        3
    AndyAO  
    OP
       2021-05-31 15:39:44 +08:00
    @momocraft #1

    你关于版本的提示非常好,这是我当前的版本↓

    PS>git --version
    git version 2.29.2.windows.2

    突然意识到很可能是因为 Sourcetree 用的是内置的 Git,这就去测试测试
    AndyAO
        4
    AndyAO  
    OP
       2021-06-01 07:25:44 +08:00
    @momocraft #1
    Sourcetree 内置的是老版本
    git version 2.24.1.windows.2
    这个版本中的行为就是那样的
    HarryQu
        5
    HarryQu  
       2021-06-01 16:18:31 +08:00
    我还是没看明白你说的什么意思。

    不想要将 embedded_repo/ 目录纳入 git 吗?

    你可以在 repo 目录创建 .gitignore,将 embedded_repo 添加到 .gitignore 中。
    AndyAO
        6
    AndyAO  
    OP
       2021-06-04 08:28:25 +08:00   ❤️ 1
    最后的方案是:
    1. 在所有中间仓库文件夹的名称后面加入后缀_ignore
    2. 然后使用递归忽略(**/*_ignore)解决问题
    实现了基本和老版本等价的效果
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5534 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 190ms · UTC 01:50 · PVG 09:50 · LAX 17:50 · JFK 20:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.