我正在尝试检查特定目录“code / app”中的所有文件和子目录,但git为我提供了代码/ app目录及其内容。我只想要它的内容。我想在post-receive git hook中使用它。
git checkout -f master -- code/app
我也试过以下无济于事
git checkout -f master -- code/app/*
git checkout -f master -- code/app/.
如何获得上述预期行为?
更新
后接收
#!/usr/bin/env ruby
# post-receive
# Read STDIN
from, to, branch = ARGF.read.split " "
if (branch =~ /master$/)
puts "Received branch #{branch}, deploying."
# Copy files to deploy directory
deploy_to_dir = File.expand_path('../development')
dir_to_checkout = '06\ -\ Code/app/'
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master -- #{dir_to_checkout}`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
exit
end
# Only deploy if pre-production branch was pushed
if (branch =~ /pre-production$/)
puts "Received branch #{branch}, deploying."
# Copy files to deploy directory
deploy_to_dir = File.expand_path('../staging')
dir_to_checkout = '06\ -\ Code/app/'
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f pre-production -- #{dir_to_checkout}`
puts "DEPLOY: pre-production(#{to}) copied to '#{deploy_to_dir}'"
exit
end
if (branch =~ /production$/)
puts "Received branch #{branch}, deploying."
# Copy files to deploy directory
deploy_to_dir = File.expand_path('../')
dir_to_checkout = '06\ -\ Code/app/'
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f production -- #{dir_to_checkout}`
puts "DEPLOY: production(#{to}) copied to '#{deploy_to_dir}'"
exit
end
答案 0 :(得分:0)
我不是Ruby专家,但幸运的是,这似乎并不重要:我可以阅读您的代码应该做的事情(虽然没有说明它是否有任何特定于Ruby的问题)。
如果我稍微改一下你的问题,你会说:
git checkout
命令主要执行我想要的操作:git checkout -f <branch> -- <dir-path>
e.g。
git checkout -f master -- Code/app/
提取名为
Code/app/somedir/somefile
的所有文件。我不喜欢的部分是,当我希望它们只在Code/app/somedir/somefile
时,它会将它们放在名为somedir/somefile
的文件中。
有 方法重命名文件,但没有一种方法简单易行,至少与仅仅进行结帐然后重命名文件相比。这样做 - 结帐,然后重命名文件 - 可能就是你应该做的。
但这里有一些微妙的问题。
首先,这种特殊形式的git checkout
只需在工作树中添加或替换文件。假设在您的某个部署分支(master
,pre-production
和production
)中,您删除某些不需要的文件。部署脚本将添加或更新任何已添加或更新的文件,但不会删除文件,因此不会从部署区域中删除已删除的文件。
(对于某些文件,你可能想要这种行为。对于#34;只是正确的文件&#34;它可能会很棘手。)
其次,您的脚本似乎部署名称以这三个名称结尾的任何分支。这在实践中可能不是问题:谁将命名他们的分支fred/master
?但是,如果有人这样做,你可能会做错事,除非 喜欢部署这样的分支。最好检查引用名称是字面refs/heads/master
,refs/heads/pre-production
和/或refs/heads/production
。
最后......好吧,这个很复杂。请记住,Git有一个名为 index 或临时区域(或有时缓存)的东西:当你git add
个文件时,你是将它们复制到索引中,当你git commit
时,Git会获取索引内容的快照,这将成为新的提交。我认为Git文档强调的一个含义是,始终的索引包含将在下一次提交中的每个文件。 (并且在提交之后,索引是不&#34;空&#34;,因为几个命令和文档的含义暗示:相反,它充满了你刚刚提交的所有内容。)< / p>
git checkout
命令利用了这个事实,这可能会让你感到悲伤。
您在这些不同的结帐命令之前设置变量GIT_WORK_TREE
,但您不设置GIT_INDEX_FILE
。因此,Git将使用 索引文件 - 每个单独的标准文件,相同的文件 - 用于这些不同的结帐命令。
Git努力优化结帐。其中一些只是为了速度,有些是因为一个&#34;开关分支&#34;故意检查不 clobber工作树更改,让您将它们带到新分支,以防您的意图。 (有关详细信息,请参阅Git - checkout another branch when there are uncommitted changes on the current branch。)无论哪种方式,Git都使用此技巧:
也就是说,假设我们假装是Git,我们正在做git checkout $branch
(有或没有-- Code/app
或其他:有和没有相似之处,但对于下一个案例我们可以使用一个测试)。我们将分支名称$branch
转换为提交ID,并将其转换为树ID,并开始查看树及其子树。我们找到了一个名为Code/app/xyz.rb
的文件。我们查看索引/缓存,并看到它有Code/app/xyz.rb
的条目。
索引的条目显示&#34; blob a123456...
已安装为Code/app/xyz.rb
,时间戳为1467505093
(2016年7月2日星期六17:18:13)。我们检查工作树文件Code/app/xyz.rb
。通过lstat
呼叫获得的时间戳为1467500000
(同一天下午3:33左右,即几小时前)。嗯,这很奇怪,它又回到过去了,但很明显它没有被改变因为我们上次检查了它 - 所以让我们把它留在原地!
但是,请问,我们是如何首先陷入这种情况的?好吧,大约两个小时前我们跑去部署pre-production
。我们(记住,&#34;我们&#34;这里是我们 - 正在Git-checkout)实际上已经将Git blob a123456...
复制到工作树Code/app/xyz.rb
时间。但是$GIT_WORK_TREE
然后是&#34; / some / path / to / preprod / area&#34;,现在它&#34; / some / path / to / master / area&#34;
我们必须在这两点之前的某个时刻部署master
,以便该文件存在于当前工作树中。但是当我们这样做时,master
的树说使用Git blob 01234567
而不是a123456
。然后,两个小时前,我们被要求部署pre-production
,并且特定Code/app/xyz.rb
已更新为版本a123456
。现在我们要求重新部署master
,其Code/app/xyz.rb
应该也为a123456
,但我们发现我们已经部署了版本{{1 - 它在索引中! - 从那时起工作树版本还没有被编辑过,所以一定很好。
(它并不好,那是不同的工作树。但我们不知道:索引不记录工作树的路径;我们&# 39;重新假设现在a123456
与$GIT_WORK_TREE
相同。)
有几种方法可以在这里起作用:
删除工作树,以便Git必须重新部署每个文件。
这种方法具有简单的优点。它的缺点是让Git复制出每个文件。当然,如果您要重命名工作树的子目录,这个&#34;只是工作&#34;无论如何,这可能是一个很好的方式。
删除索引(缓存),以便Git必须重新部署每个文件。
这几乎和以前一样。 Git将重建索引。
每个工作树使用一个索引。
这是最复杂的方法,但应该是最有效的方法。此外,它是新的(自Git版本2.5)$GIT_WORK_TREE
命令以及git worktree add
将隐藏所有复杂性。如果你的Git足够新,你可以用新的worktree功能替换这个有点复杂的部署脚本。
答案 1 :(得分:0)
只需执行基础操作,不要费心更新(甚至检查)HEAD
:
git read-tree -um `git write-tree` master:code/app
绕过便利命令并直接执行您想要的操作。你没有检查开发分支,没有提交你正在检查的内容。 git write-tree
现在为树中的列表中的列出,master:code/app
命名master
提交中的树,双树git read-tree -um
在索引和工作树中进行转换。
如果您要维护多个工作树,请通过将GIT_INDEX_FILE
导出为“$GIT_DIR/index
”之外的内容来维护每个工作树的索引。
答案 2 :(得分:0)