不在git目录中时进行git pull


308

假设我有一个目录/X/Y,这是一个git存储库。是否可以通过某种方式调用git pull来自inside 的命令/X,但以/X/Y目录为目标?

编辑:我想我特别想知道:是否可以使用git命令来执行此操作,而不必更改目录?

注意:我已经接受VonC的答案,因为它比以前的选项要优雅得多。对于运行Git 1.8.5之前的版本的人,请参见下面的bstpierre答案


2
我想补充一点,除非您未设置GIT_DIR,否则在钩子中使用git-pull时将不起作用。相关的。
zpmorgan

从git 1.8.5(2013年第四季度)开始,您将能够“使用git命令,而不必更改目录”。请在下面
VonC

Answers:


453

git 1.8.5(2013年第四季度)开始,您将能够“使用Git命令,而不必更改目录”。

就像“ make -C <directory>”一样,git -C <directory> ...”告诉Git在做其他事情之前要去那里

提交44e1e4纳兹里Ramliy

在不离开当前目录的情况下,需要更多的按键才能调用其他目录中的Git命令:

  1. (cd ~/foo && git status)
    git --git-dir=~/foo/.git --work-tree=~/foo status
    GIT_DIR=~/foo/.git GIT_WORK_TREE=~/foo git status
  2. (cd ../..; git grep foo)
  3. for d in d1 d2 d3; do (cd $d && git svn rebase); done

上面显示的方法可用于脚本编写,但对于快速命令行调用而言则过于繁琐。

使用此新选项,可以用更少的击键完成上述操作:

  1. git -C ~/foo status
  2. git -C ../.. grep foo
  3. for d in d1 d2 d3; do git -C $d svn rebase; done

自Git 2.3.4(2015年3月)以来,由Karthik Nayak(提交6a536e2,将将“ ”视为无操作KarthikNayakgitgit -C '<path>'<path>

' git -C ""'无故死于错误“ Cannot change to ''”,而shell将cd“”“视为无操作。
以shell的行为为先例,还教导git将-C“”'视为无操作。


4年后,Git 2.23(Q3 2019)证明了' git -C ""'有效并且不会更改目录

自6a536e2以来,它的行为一直如此(git:空git -C '<path>'时将“ ”视为无操作<path>,2015-03-06,Git v2.3.4)。

这意味着现在(最终)的文档包括:

如果' <path>'存在但为空,例如-C "",则当前工作目录保持不变。


您可以看到git -C与Git 2.26(Q1 2020)一起使用的示例。

请参阅提交b441717提交9291e63提交5236fce提交10812c2提交62d58cd提交b87b02c提交9b92070提交3595d10提交f511bc0提交f6041ab提交f46c243提交99c049b提交3738439提交7717242提交b8afb90(2019年12月20日)由Denton Liu(Denton-L)撰写
(通过合并JUNIOÇ滨野- gitster-提交381e8e9,2020年2月5日)

t1507: 排队 full_name()

签字人:刘丹顿

以前,我们在跑步test_must_fail full_name。但是,test_must_fail仅应在git命令上使用。
内联,full_name()以便我们可以直接test_must_failgit命令上使用。

full_name()28fb84382b中引入(“ Introduce <branch>@{upstream}符号”,2009-09-10,Git v1.7.0-rc0- merge)时,该git -C选项尚不可用(因为它是在44e1e4d67d中引入的(“ git:在给定的目录中运行使用-C选项”,2013-09-09,Git v1.8.5-rc0- 合并批次#5中列出))。
结果,助手功能消除了cd每次手动操作的需要。但是,由于git -C现在可用,因此我们可以改为使用inline full_name()


6
喔不错哟!这种方式更优雅,因此我将其标记为将来的观众接受。
加文·安德列格

1
对我不起作用:#git --version && git -C〜/ .m2 /检出主git版本1.8.3.4(Apple Git-47)未知选项:-C用法:git [--version] [--help ] [-c名称=值] [--exec路径[= <路径>]] [--html路径] [--man路径] [--info路径] [-p | --paginate | --no-pager] [--no-replace-objects] [--bare] [--git-dir = <path>] [--work-tree = <path>] [--namespace = <name> ] <command> [<args>]
Jan Galinski 2014年

7
@JanGalinski但是我确实提到了“启动git 1.8.5”。因此git 1.8.3.x尚不知道该选项。
VonC 2014年

2
在Ubuntu 12.04上,我必须安装较新的git版本。我这样做是这样的:apt-get install software-properties-common python-software-properties然后添加git repo add-apt-repository ppa:git-core/ppa。最后一步是更新的git: apt-get update && apt-get upgrade
ph3nx 2014年


54

编辑

要么存在bug git pull,要么无法使用该命令执行操作。但是,您可以通过获取和合并来实现:

cd /X
git --git-dir=/X/Y/.git fetch
git --git-dir=/X/Y/.git --work-tree=/X/Y merge origin/master

原始答案

假设您正在运行bash或类似工具,则可以这样做(cd /X/Y; git pull)

git的手册页指定一些变量(请参阅“Git仓库”),似乎像他们应该帮助,但我不能让他们的工作权利(与我的仓库在/ tmp / ggg2):

GIT_WORK_TREE=/tmp/ggg2 GIT_DIR=/tmp/ggg2/.git git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.

当我的cwd为/ tmp时运行以下命令会更新该存储库,但更新的文件将显示在/ tmp而不是工作树/ tmp / ggg2中:

GIT_DIR=/tmp/ggg2/.git git pull

另请参见类似问题的答案,该问题演示了--git-dir--work-tree标志。


您是否尝试仅使用GIT_WORK_TREE?
Arrowmaster

@Arrowmaster:是的,如果这样做,git找不到.git目录。
bstpierre 2011年

不错,手册页说如果未设置GIT_DIR,则不使用GIT_WORK_TREE。两者同时使用时,它不起作用似乎很奇怪。
Arrowmaster

@Arrowmaster:我想知道这里是否有错误。如果这样做git --git-dir=/tmp/ggg2/.git --work-tree=/tmp/ggg2 pull,我会收到一条错误消息。但是,如果我git --git-dir=/tmp/ggg2/.git --work-tree=. pull在/ tmp中时这样做,则会将更新的文件按原样放在/ tmp中。
bstpierre 2011年

@bstpierre:我没有获得与现在安装的git的系统,但如果我这样做我会尝试其他的替代品与--work-tree现在一样--work-tree=/tmp/ggg2/,并--work-tree=/tmp/ggg2/.因为它可能是与它如何解析路径的问题。
Arrowmaster

32

您可以将其包装在bash脚本或git别名中:

cd /X/Y && git pull && cd -

1
这绝对可以解决问题,但是我想知道是否有某种方式可以使用git命令而不更改目录。我开始认为没有。
加文·安德列格

1
并使用该pushd/popdcd/cd-
货币

或者,您可以使用子外壳来防止必须CD退回:(cd xyz && git pull)
jarmod

30

这篇文章有点老了,所以可能有一个错误并且已经修复,但是我只是这样做了:

git --work-tree=/X/Y --git-dir=/X/Y/.git pull origin branch

而且有效。花了我几分钟来弄清楚它想要点文件和父目录(在标准设置中,它们始终是父/子目录,但在所有设置中却不是,因此需要明确指定它们。


我喜欢这种解决方案,因为它可用于\\ remotemachine \ C $ \ folder \ etc等目录
twasbrillig 2013年

7

由于我的某些服务器在旧的Ubuntu LTS版本上,因此我无法轻易将git升级到最新版本(如某些答案中所述,它支持-C选项)。

这个技巧对我来说效果很好,尤其是因为它没有其他一些答案的副作用,这些其他答案使您离开了起始位置。

pushd /X/Y
git pull
popd

或者,将其作为单线执行:

pushd /X/Y; git pull; popd

Linux和Windows都具有push和popd命令。


5

使用和组合pushd,我们可以实现以下功能:git pullpopd

pushd <path-to-git-repo> && git pull && popd

例如:

pushd "E:\Fake Directory\gitrepo" && git pull && popd

这真太了不起了。完美工作
Stretch0

4

您可以编写如下脚本:

cd /X/Y
git pull

您可以将其命名为gitpull
如果您希望它执行任意目录,而不是/X/Y

cd $1
git pull

然后,您可以使用来调用它。gitpull /X/Z
最后,您可以尝试查找存储库。我有一个~/git包含存储库的文件夹,您可以使用它对所有存储库进行提取。

g=`find /X -name .git`
for repo in ${g[@]}
do
    cd ${repo}
    cd ..
    git pull
done

2
如果要从命令行执行此操作,只需在以下子shell中执行:(cd /X/Y && git pull)
卡斯卡贝尔2011年

2

对于像我这样试图通过远程服务器上的drush(Drupal shell)命令执行此操作的任何人,您将无法使用需要CD进入工作目录的解决方案:

相反,您需要使用将提取分解为获取和合并的解决方案:

drush @remote exec git --git-dir=/REPO/PATH --work-tree=/REPO/WORKDIR-PATH fetch origin
drush @remote exec git --git-dir=/REPO/PATH --work-tree=/REPO/WORKDIR-PATH merge origin/branch

1

这可能是一个类似的问题,但是您也可以简单地链接命令。例如

一行上

cd ~/Sites/yourdir/web;git pull origin master

或通过SSH。

ssh username@atyourserver.com -t "cd ~/Sites/thedir/web;git pull origin master"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.