Bash 通过预接收挂钩在git push上测试推送冲突
我正在BitBucket上制作一个预接收钩子,用来确认分支中的所有推送都是父分支的最新推送 我的意思是,在时间进化中,我们有几个分支: 对于上面的示例os 3分支,Dev、Feature1和my Local,我想在将本地推送到远程/origins/Feature1之前,将最新的特性1与最近的推送本地代码进行git合并。通过这种方式,我可以确认,无论是谁在推送,都在使用feature1的最新版本,不会有冲突。 如果有任何冲突,我会返回1,以避免推!并且要求开发人员在推送代码之前从特性中提取代码 这是我在预接收钩子上的脚本Bash 通过预接收挂钩在git push上测试推送冲突,bash,git,githooks,git-push,Bash,Git,Githooks,Git Push,我正在BitBucket上制作一个预接收钩子,用来确认分支中的所有推送都是父分支的最新推送 我的意思是,在时间进化中,我们有几个分支: 对于上面的示例os 3分支,Dev、Feature1和my Local,我想在将本地推送到远程/origins/Feature1之前,将最新的特性1与最近的推送本地代码进行git合并。通过这种方式,我可以确认,无论是谁在推送,都在使用feature1的最新版本,不会有冲突。 如果有任何冲突,我会返回1,以避免推!并且要求开发人员在推送代码之前从特性中提取代码
while read from_ref to_ref ref_name; do
echo "Ref update:"
echo " Old value: $from_ref"
echo " New value: $to_ref"
echo " Ref name: $ref_name"
echo " Diff:"
git clone --progress -v $GIT_URL $CLONE_DIR1
cd $CLONE_DIR1
git checkout -b test remotes/origin/Feature1
git merge --no-commit -m "Merging feature with local on-push code" $ref_name
(....)
done
我试过使用ref_name,to_ref,但没有成功
有人能帮我吗
如何访问最近推送的代码,并按父分支与此代码合并?这似乎是一件非常奇怪的事情,而且可能注定要失败。这肯定会很复杂,您需要根据正在更新的ref以及这些更新是否添加合并提交来更改测试行为 这就是说,预接收和更新挂钩有一些特殊规则,如果您遵守这些规则,您将获得更高的收益:
chdir
或cd
离开当前目录。或者,如果您这样做了,请确保返回chdir
,但通常不太难确保必须在另一个目录中运行的操作作为单独的进程运行:一个子shell或另一个脚本$GIT\u DIR
。原因是钩子在顶级目录中运行,并且$GIT\u DIR
设置为.GIT
(非裸repo)或
(裸存储库)exitstatus=0
while read from_ref to_ref ref_name; do
... maybe some setup code here to see if $ref_name
is being created or destroyed ...'
case "$ref_name" in
... add cases as needed to choose action based on ref ...
if (unset GIT_DIR; /path/to/check_script arg1 arg2 ...); then
echo "push being rejected because ..."
exitstatus=1
fi
...
esac
...
done
exit $exitstatus
这里还有一个很大的问题。您希望check\u script
能够访问任何建议的新提交,如果钩子脚本退出0,则可以从$ref\u name
访问这些提交,以便允许对其进行建议的更新。该更新尚未发生:$ref\u name
仍然指向旧的SHA-1$from\u ref
。同时,$to_ref
中的新SHA-1可能没有任何名称指向它(尽管它仍然存在于基础存储库中)
除此之外,如果$to_ref
指向新提交(通常情况下),此时通过正常git操作进行的任何克隆都不会包含这些提交,因此您将无法使用它们
有两种明显的方法来处理这个问题:
- 创建一个指向
的新(临时)引用。然后,您可以在克隆中看到建议的提交$to\u ref
- 不要使用克隆。以其他方式复制存储库,或直接使用原始存储库本身,例如,作为“替代”,或通过创建临时工作树目录并将
指向该目录,或使用GIT 2.6+中出现的一些新的$GIT_work_tree
功能。(如果选择手动临时工作树方法,请务必同时考虑正常的共享GIT worktree
)$GIT_INDEX_文件
#!/bin/bash
DIR=xpto/external-hooks/code_review
CLONE_DIR=$DIR/test_conflict_push-$(date +%s)
GIT_URL=myGitUrl
exitStatus=0
read oldrev newrev refname
feature_branch=${refname##refs/heads/}
echo "Feature branch-> $feature_branch"
#Clone feature branch from remote repo to be update via merged.
git clone --progress -v $GIT_URL $CLONE_DIR
currentDir=$PWD
cd $CLONE_DIR
#create branch named 'latest' to put new and modify files
git checkout -b latest remotes/origin/$feature_branch
#go back to PWD otherwise cant make git diff
cd $currentDir
# Get the file names, without directory, of the files that have been modified
# between the new revision and the old revision
echo "Getting files"
files=`git diff --name-only ${oldrev} ${newrev}`
echo "Files -> $files"
# Get a list of all objects in the new revision
echo "Getting objects"
objects=`git ls-tree --full-name -r ${newrev}`
echo "objects -> $objects"
# Iterate over each of these files
for file in ${files}; do
# Search for the file name in the list of all objects
object=`echo -e "${objects}" | egrep "(\s)${file}\$" | awk '{ print $3 }'`
# If it's not present, then continue to the the next itteration
if [ -z ${object} ];
then
continue;
fi
# Otherwise, create all the necessary sub directories in the new temp directory
mkdir -p "${CLONE_DIR}/`dirname ${file}`" &>/dev/null
# and output the object content into it's original file name
git cat-file blob ${object} > ${CLONE_DIR}/${file}
done;
echo "Ready for start merging."
cd $CLONE_DIR
#add new files to branch
echo $(git add .)
#commit added and modify files to branch
echo $(git commit -a -m "Merge latest to original feature")
#get generated commit id
echo $(git log -1)
#create branch named 'merged' to merge above commited files
echo $(git checkout -b merged remotes/origin/$feature_branch)
#merge only occurs for madded and modify files!
echo "Merging committed files to 'merged' branch with from 'latest' branch."
mergeResult=$(git merge --no-commit latest)
echo "Merge Result -> $mergeResult"
##to lower case
if [[ "${mergeResult,,}" == *"conflict"* ]]
then
echo "Merge contains conflicts."
echo "Update your $feature_branch branch!"
exitStatus=1
else
echo "Merge don't contains conflict."
echo "Push to $feature_branch can proceed."
exitStatus=0
fi
#remove temporary branches
echo $(git checkout master)
echo $(git branch -D latest)
echo $(git branch -D merged)
#delete temporary clone dir
rm -rf $CLONE_DIR
exit $exitStatus
非常感谢