Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将.gitignore添加到Git中存储库中的所有分支?_Git_Github - Fatal编程技术网

如何将.gitignore添加到Git中存储库中的所有分支?

如何将.gitignore添加到Git中存储库中的所有分支?,git,github,Git,Github,我的存储库中有5个以上的分支。 我想将.gitignore文件添加到每个分支,并将其推送到远程存储库 在克隆远程存储库之后,我尝试逐个运行以下命令 我按顺序运行的命令: for branch in $(git branch --all | grep '^\s*remotes' | egrep --invert-match '(:?HEAD|master)$'); do git branch --track "${branch##*/}" "$branch"; done for bran

我的存储库中有5个以上的分支。 我想将.gitignore文件添加到每个分支,并将其推送到远程存储库

在克隆远程存储库之后,我尝试逐个运行以下命令

我按顺序运行的命令:

 for branch in $(git branch --all | grep '^\s*remotes' | egrep --invert-match '(:?HEAD|master)$'); do    git branch --track "${branch##*/}" "$branch"; done

for branch in $(git branch); do    git checkout $branch && touch .gitignore; done

for branch in $(git branch); do    git checkout $branch && git status; done

for branch in $(git branch); do    git checkout $branch && echo ".classpath" >> .gitignore && echo ".project" >> .gitignore && echo ".settings/" >> .gitignore && echo "log/" >> .gitignore && echo "target/" >> .gitignore ; done

for branch in $(git branch); do    git checkout $branch && git add .gitignore; done

for branch in $(git branch); do    git checkout $branch && git commit -m 'Adding gitignore'; done

for branch in $(git branch); do    git checkout $branch && git push -u origin $branch; done
不知道,但它的性能不如预期


请提供帮助。

首先,
git branch
是为了用户友好,而不是编程友好。不要将其用于编程:使用编程友好的“管道”命令,
git用于每个ref

其次,正如编写脚本一样——一次性脚本是个好主意,如果需要,在新的(新鲜、干净的)克隆上重复编写和使用脚本要容易得多,直到通过一个循环完成循环中所有必要的操作

最后,根本不要在这里进行git推送。分开做。Git有一种内置的方式来推动“所有分支”

您的第一个循环读取(使用我的格式):

这看起来像是您希望使用现有的远程跟踪分支(
origin/*
或其他任何分支)并从中创建新的本地分支,将新的本地分支设置为将相应的远程跟踪分支作为其上游。出于某种原因(我想我知道原因),您排除了
master
,并且您还排除了恼人的符号HEAD ref,它显示为:

  remotes/origin/HEAD -> origin/master
其余循环不排除
master
(但也无法处理
git分支打印的
*
,因此它们至少会产生一些错误消息)。因此,看起来您也希望在
master
上执行此操作。这意味着您可能在第一个循环中跳过它,因为它已经存在,这在新克隆中通常是真的

因此,让我们编写一些我们希望在新的
git克隆上运行的东西,即除了
master
之外没有分支的克隆。(尽管如此,请再次参阅脚注1。)在此过程中,我们还将尝试修复其他错误

有一个小问题:我们在这里假设远程分支的名称是
origin
,因此远程跟踪分支的名称以
refs/remotes/origin/
开头。这使得在所有名称上循环并去掉
origin/
前缀更加容易。我们将从以下内容开始我们的脚本:

for name in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin); do
这将迭代所有缩短的名称:
origin/HEAD
origin/master
,等等

接下来,我们想跳过那些实际上是符号引用的,比如
HEAD
。我们可以跳过文字标题,这要简单得多。奇特的方法是使用
git symbolic ref
来测试它,但是没有意义,我们将看到的唯一实际的一个(出于历史原因)是HEAD,所以让我们这样做:

    [ "$name" = origin/HEAD ] && continue
现在我们需要做的是创建并签出一个本地分支,该分支将相应的远程跟踪分支设置为其上游。我们可以使用内置的
git checkout
轻松完成这一任务

这也让我们避免了特殊的大小写
master
git clone
已经运行
git checkout master
,它创建了
master
,并将其设置为
origin/master
作为其上游,但无论如何我们都需要使用
git checkout master
。这将签出创建的
git clone
的现有
master
(当
git clone
运行
git checkout master
时)。因此,我们的下一步是构造正确的分支名称:

    branch=${name#origin/}
    git checkout $branch
例如,如果一个远程跟踪分支被命名为
origin/feature/life
,另一个被命名为
origin/feature/zorg
,我们只想剥离
origin/
,而不是“直到最后一个斜杠的所有内容”。我们需要本地
feature/life
,从中我们可以更新
origin/feature/life

如果分支是
主分支
,则该分支已存在,并将其签出。如果分支是其他分支,则它不存在,但由于这是一个新的克隆,因此只有一个远程跟踪分支存在,即具有
$name
-的分支,因此我们将创建本地分支并将其签出,并将远程跟踪分支设置为其上游分支

现在我们要创建一个
.gitignore
,在其中放入一堆东西,添加它,然后提交它。一个重要的问题是,
.gitignore
是否已经存在于我们刚刚签出的提交中,如果已经存在,我们想对此做些什么。我不能为你回答那个问题。另一个问题是我们将要添加到此
.gitignore
中的任何文件是否存在于我们刚刚签出的提交中,如果存在,该怎么办。再说一遍,我不能回答这个问题。但是,我要注意,
touch.gitignore
后跟
git status
仅当
.gitignore
是由
touch
新创建的时才会打印内容。直接测试可能更明智:

    if [ -f .gitignore ]; then
        ... do whatever should be done here ...
    else
        ... create it ...
    fi
如果“应该做什么”是“没有什么特别的”,我们就可以更容易地做,因为我们可以简单地使用
>
添加到它,如果它不存在,它将创建它,如果它确实存在,则添加到它

而不是五个独立的
echo…>>。gitignore
,我们可以使用一个
cat>.gitignore
和一个“here document”:

将所有这些写入shell脚本文件(
/tmp/doit.sh
/tmp/t.sh
是我最喜欢的脚本名称)。添加一个
#/bin/sh-e
行或
在顶部设置-e
并使文件可执行
-e
确保脚本在任何命令因任何原因失败时退出。(也为调试添加
set-x
)在循环之前添加显式的
git clone
行,以便它克隆存储库,这样我们就可以确保有一个新的克隆。请记住将目录也更改为克隆

剩下的
    if [ -f .gitignore ]; then
        ... do whatever should be done here ...
    else
        ... create it ...
    fi
    cat << END >> .gitignore
.classpath
.project
.settings
log/
target/
END
    git add .gitignore
    git commit -m 'add gitignore'
done
#! /bin/sh -e
# set -x  # for debug
[ -d newrepo ] && { echo "error: newrepo directory already exists"; exit 1; }
git clone scheme://example.com/path/to/repo.git newrepo
cd newrepo
for name in ... # see above for the rest
$ cd newrepo
$ git push origin 'refs/heads/*:refs/heads/*'
#! /bin/sh -e
# set -x  # for debug
[ -d mydir] && { echo "error: mydir directory already exists"; exit 1; }
git clone <git-repo-url> mydir
cd mydir
for name in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin); do
     [ "$name" = origin/HEAD ] && continue
     branch=${name#origin/}
     git checkout $branch
     echo ".classpath" >> .gitignore && echo ".project" >> .gitignore && echo ".settings/" >> .gitignore && echo "log/" >> .gitignore && echo "target/" >> .gitignore
     git add .gitignore
     git commit -m 'adding gitignore'
done
git push origin 'refs/heads/*:refs/heads/*'