我已经进行了广泛的搜索,阅读了很多SO问题和解决方案并尝试了不同的方式,但我一直无法做我想做的事情,这很简单。
我有主分支,其中包含所有主代码,以及设计分支,其中rails应用程序的布局由设计团队构建。他们在公共文件夹中添加了一个名为“photoshop”的文件夹,以便在版本控制下保持图像的来源。但我不希望在合并到主分支时复制此文件夹,因为它是不需要的。
显然,这样做的方法是通过合并驱动程序。所以,我创建了“忽略”驱动程序:
[merge "ignore"]
name = always ignore during merge
driver = ignore.sh %0 %A %B
在我的$ PATH上创建了ignore.sh文件:
exit 0
我在public /中创建了.gitattributes文件,因为photoshop文件夹应该整体被忽略,它将出现在public /:
下photoshop merge=ignore
photoshop/ merge=ignore
photoshop/* merge=ignore
photoshop/**/* merge=ignore
正如您所看到的,我尝试了几种不同的模式来忽略整个文件夹,但它不起作用。我相信这是因为master分支上没有文件夹,所以没有冲突,因此git不使用ignore驱动程序。有没有办法实现这一点,而无需在master上创建public / photoshop文件夹?
谢谢!
答案 0 :(得分:18)
正如我的另一个答案所示,这里是解决方案的扩展,通用,工业级版本。
(是的,我在家里很无聊,没有别的事可做:P)
此脚本将根据您的本地设计分支添加新的分离的提交,因此它不会影响设计存储库或设计分支。提交将删除所有所需的文件。然后它执行合并。
对于那些懒得阅读完整代码的人来说,"核心"这些步骤可以简化为:
original=$(gitbranch HEAD) # current branch name, or sha1 if not in a branch
branchsha=$(gitsha "$branch") # sha1 of a ref, to force detached commit
git checkout "$branchsha" &&
git rm -rf "${files[@]}" &&
git commit -m "$msgcommit" &&
newsha=$(gitsha HEAD) &&
git checkout "$original" &&
git merge -m "$msgmerge" "${mergeopts[@]}" "$newsha"
以下是完整的脚本:
(稍微修改以应对弱且有限的SO语法着色,因此从下面的链接获取原始来源更好)
#!/bin/bash
#
# git-strip-merge - a git-merge that delete files on branch before merging
#
# Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not see <http://www.gnu.org/licenses/gpl.html>
#
# Answer for "How to setup a git driver to ignore a folder on merge?"
# See http://stackoverflow.com/questions/3111515
#Defaults:
msgcommit="remove files from '<branch>' before merge"
msgmerge="Merge stripped branch '<branch>'"
verbose=0
quiet=(--quiet)
usage() {
cat <<- USAGE
Usage: $myname [git-merge options] [-M <commitmsg>] <branch> FILE...
USAGE
if [[ "$1" ]] ; then
cat >&2 <<- USAGE
Try '$myname --help' for more information.
USAGE
exit 1
fi
cat <<-USAGE
"git-merge that delete files on "foreign" <branch> before merging
Useful for ignoring a folder in <branch> before merging it with
current branch. Works by deleting FILE(S) in a detached commit based
on <branch>, and then performing the merge of this new commit in the
current branch. Note that <branch> is not changed by this procedure.
Also note that <branch> may actually be any reference, like a tag,
or a remote branch, or even a commit SHA.
For more information, see <http://stackoverflow.com/questions/3111515>
Options:
-h, --help
show this page.
-v, --verbose
do not use -q to supress normal output of internal steps from git
checkout, rm, commit. By default, only git merge output is shown.
Errors, however, are never supressed
-M <message>, --msgcommit=<message>
message for the removal commit in <branch>. Not to be confused
with the message of the merge commit, which is set by -m. Default
message is: "$msgcommit"
-m <message>, --message=<message>
message for the merge commit. Since we are not merging <branch>
directly, but rather a detached commit based on it, we forge a
message similar to git's default for a branch merge. Otherwise
git would use in message the full and ugly SHA1 of our commit.
Default message is: "$msgmerge"
For both commit messages, the token "<branch>" is replaced for the
actual <branch> name.
Additional options are passed unchecked to git merge.
All options must precede <branch> and FILE(s), except -h and --help
that may appear anywhere on the command line.
Example:
$myname design "photoshop/*"
Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
License: GPLv3 or later. See <http://www.gnu.org/licenses/gpl.html>"
USAGE
exit 0
}
# Helper functions
myname="${0##*/}"
argerr() { printf "%s: %s\n" "${0##*/}" "${1:-error}" >&2 ; usage 1 ; }
invalid() { argerr "invalid option: $1" ; }
missing() { argerr "missing ${2:+$2 }operand${1:+ from $1}." ; }
# Option handling
files=()
mergeopts=()
for arg in "$@"; do case "$arg" in -h|--help) usage ;; esac; done
while (( $# )); do
case "$1" in
-v|--verbose ) verbose=1 ;;
-M ) shift ; msgcommit=$1 ;;
-m ) shift ; msgmerge=$1 ;;
--msgcommit=* ) msgcommit=${1#*=} ;;
--message=* ) msgmerge=${1#*=} ;;
-* ) mergeopts+=( "$1" ) ;;
* ) branch="$1"
shift ; break ;;
esac
shift
done
files+=( "$@" )
# Argument handling
msgcommit=${msgcommit//<branch>/$branch}
msgmerge=${msgmerge//<branch>/$branch}
[[ "$msgcommit" ]] || missing "msgcommit" "MSG"
[[ "$branch" ]] || missing "" "<branch>"
(( ${#files[@]} )) || missing "" "FILE"
((verbose)) && quiet=()
# Here the fun begins...
gitsha() { git rev-parse "$1" ; }
gitbranch() {
git symbolic-ref "$1" 2> /dev/null | sed 's/refs\/heads\///' ||
gitsha "$1"
}
original=$(gitbranch HEAD)
branchsha=$(gitsha "$branch")
trap 'git checkout --quiet "$original"' EXIT
git checkout "$branchsha" "${quiet[@]}" &&
git rm -rf "${files[@]}" "${quiet[@]}" &&
git commit -m "$msgcommit" "${quiet[@]}" &&
newsha=$(gitsha HEAD) &&
git checkout "$original" "${quiet[@]}" &&
git merge -m "$msgmerge" "${mergeopts[@]}" "$newsha"
享受!
一张图片胜过千言万语......
合并前:
合并后:
请注意&#34;设计&#34;由于分离的提交技巧,分支提示根本没有受到影响,即使是本地分支也是如此。除此之外,两个提交(删除和合并)都是常规提交,具有合适的提交消息和父母。并且&#34;掌握&#34; branch是干净的任何不需要的文件。
答案 1 :(得分:10)
不是本身的答案,而是关于.gitignore
的一些注意事项:在您的方案中 将帮助您。
.gitignore
用于忽略工作树中的文件添加到 index (暂存区域)。因此,它仅在您使用git add <files>
时有效,并且仍然可以使用git add --force <files>
覆盖它。它只是为了方便防止添加不需要的文件,但它对存储库中的文件没有影响
在您的方案中,不需要.gitignore
,因为您没有任何本地./photoshop
文件夹,因此您永远不会有任何photoshop文件要添加到您的文件夹中主分公司。但是,创建一个以防万一,也不会有什么坏处。对于设计团队.gitignore
不受欢迎,因为他们希望将photoshop文件添加到他们的分支。
因此,由于合并处理已提交数据,并且./photoshop
文件已经存储在存储库中,因此使用合并驱动程序的方法是正确的。
问题是......默认情况下,只有在冲突 的情况下才会触发合并驱动程序。而且,由于master
分支没有任何./photoshop
个文件夹或文件,根本没有冲突,它们被完全合并。所以你的合并驱动程序也没有任何影响,无论你的路径模式如何(顺便说一下,你的第二个,photoshop/
是正确的)。我不知道是否可以将git merge配置为触发合并驱动程序,即使是非冲突的文件,但是值得谷歌搜索。
正如我之前所说,我的答案不是你问题的真正解决方案。我只希望对这个问题有所了解,解释为什么你使用合并驱动程序和.gitignore的尝试都失败了。我建议阅读更多(配置)合并驱动程序。 子模块也值得研究。
希望这有帮助!
<强>更新强>
Maybe my other answer will help you:
Usage: git-strip-merge [git-merge options] [-M <commitmsg>] <branch> FILE...
享受!
答案 2 :(得分:0)
您是否尝试在.gitignore
分支中添加master
文件,以忽略任何photopshop
目录内容?
然后,从设计到master
的合并不应在master
中添加新目录。
如果这样做,您仍然需要合并驱动程序,但这次要管理.gitignore
文件的内容。