Git - 如何在目录中查找所有项目的“未推送”提交?

13

我终于开始习惯使用Git了,经过最初的陡峭学习曲线后,我必须说这很不错(只是我想念单个文件外部引用,但那是另一个故事)。然而,我有一个问题无法解决:我目前正在同时处理十几个项目。它们都相互关联,我必须在其中一个和另一个之间跳转,并在此处进行更改。

到目前为止还好,我可以相当轻松地“把握”它们,我定期提交更改等。问题是,几个小时后,我不记得我推送到远程仓库的哪些项目。当然,我可以“cd”进入每个项目的目录并发出推送命令,但这很繁琐。我在想是否有一种方法,使用bash来运行类似于git查找所有未推送的提交,在此目录中的所有项目。这样的命令将从不是Git存储库的目录中运行,但其中包含所有项目的树。

逻辑很简单,但实现起来似乎非常复杂,因为尽管根目录包含了所有项目,但实际的Git存储库可以在起始目录的任何级别上找到。例如:

  • projects目录
    • 客户 X
    • project1(Git存储库)
    • 客户 U
    • project2(Git存储库)
    • project3
      • somelibrary(Git存储库)
      • theme(Git存储库)

在此示例中,只有粗体字的目录是Git存储库,因此应在其中运行检查。我知道这个结构看起来有点乱,但实际上很容易处理。

任何帮助都受到欢迎,谢谢。

8个回答

12

你可以使用 git cherry 查找未推送的提交,因此你应该能够编写一个类似于以下的 Bash 脚本:

#!/bin/bash
for file in `find ./ -type d -maxdepth 3` ; do
    cd $file
    git cherry -v
    cd -
done

以下命令可以查找三层子目录,但可能不太美观。

编辑

如Evan建议的那样,您可以使用子shell避免返回到上一级目录,例如:

#!/bin/bash
for file in `find ./ -type d -maxdepth 3` ; do
    (cd $file && git cherry -v)
done

你可能想在这里添加一个pwd命令来查看你所在的文件/目录...


2
不必使用 cd - 切换到上一个目录,你可以将循环体作为子shell来执行。 - user1655874
只需使用 find + git,无需使用 shell:find . -name .git -type d -print -exec git --git-dir={} --work-tree={}/.. cherry -v \; - Ruslan
我创建了一个开发者工具,可以完成这个任务,并打印出所有的元数据,还可以执行git pull操作。请访问https://github.com/eighty4/maestro。 - undefined

9
您可以尝试使用git子模块,但个人认为它们不易于使用。因此我之前创建了一个脚本来处理一组git仓库:https://github.com/mnagel/clustergit clustergit允许您同时在多个存储库上运行git命令。特别是递归地在一个文件夹上运行git status非常有用。clustergit支持git statusgit pullgit push等命令。 enter image description here

1
这应该随 git 一起发布。 - debuglevel

6
您可以使用以下一行代码,在您所需的非Git存储库目录中进行搜索。这将列出未推送提交的git存储库的绝对路径:
find . -type d -iname '.git' -exec sh -c 'cd "${0}/../" && git status | grep -q "is ahead of" && pwd' "{}" \;

这是通过递归搜索.git目录来实现的,当找到后,会进入其父目录,也就是git项目根目录。然后运行git status并使用grep查找“is ahead of”短语。如果为真,则执行'pwd'命令之后的命令,例如可以插入您自己的命令(例如显示未推送提交)。注意:仅适用于活动分支上未推送的提交。

这适用于所有分支还是只适用于活动分支? - Dan Stevens
1
很遗憾,@DanStevens,我刚刚测试了一下,没有找到正确的方法来显示仅在远程跟踪分支上未推送的提交。 - Qetesh

6
将顶层目录作为git仓库,将每个项目作为子模块。现在您可以运行:
git submodule foreach --recursive git status # or any other command

如果您的项目中没有任何子模块,那么就不需要使用递归。


4
以下命令也支持带有空格的路径,并且只会检查包含 .git 子目录的目录。
每个存储库(所有分支)未推送更改的数量:
while IFS= read -r -d '' dir; 
    do 
        ([ -d "$dir/.git" ] && cd "$dir" && echo -n `pwd`\
        && echo " [ UNPUSHED: "`git log --branches --not --remotes | grep "^commit" | wc -l`" ]" ); 
    done < <(find -type d -print0)

每个仓库未提交的文件数量(分为暂存和未暂存):

while IFS= read -r -d '' dir; 
    do 
        ([ -d "$dir/.git" ] && cd "$dir" && echo -n `pwd`\
         && echo " [ UNCOMMITTED: "`git status -s | wc -l`" ]"); 
    done < <(find -type d -print0)

注意:如果未设置上游(-u),则git cherry无法工作,而上面的git log可以。


2

以下是针对使用fish的用户的答案,基于JKirchartz的回答进行了一些微调:

for file in (find . -type d -maxdepth 3)
  if test -d "$file/.git"
    fish -c "cd $file; and git cherry -v; and pwd"
  end
end

2

将此别名添加到您的.gitconfig文件中,然后您就可以从父目录运行git status-all以递归方式获取所有git存储库的状态。

[alias]
status-all = "!for d in `find . -name \".git\"`; do echo \"\n*** Repository: $d ***\" && git --git-dir=$d --work-tree=$d/.. status; done"

See also this post.


0
Maestro开发工具具有同步功能,可以打印所有存储库的本地状态(暂存、本地更改、本地提交),并执行git pull操作。
# install
curl -fsSL https://maestro.eighty4.tech/install.sh | sh

# do a git sync on all repositories, walking subdirectories to a depth of 2
maestro git

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