سؤال

أحاول إعداد git لتنظيم موقع الويب الخاص بي حتى أتمكن من ذلك git pull للحصول على الإصدار الحالي للعمل محليًا ثم git push لدفع التغييرات إلى الخادم البعيد. لقد تم إعداده حتى يعمل بالطريقة التي أريدها ، لكن بعد أن دفعت ، يجب أن أركض يدويًا git checkout -f أو git reset --hard HEAD على الخادم البعيد.

لقد حاولت وضعها في برنامج نصي shell كخطاف ما بعد الاستقبال على الخادم ، لكن يبدو أنه لا يكون له أي تأثير. أعلم أن البرنامج النصي يعمل لأنني أرى "تغييرات تم دفعها إلى الخادم" بعد الضغط. ها هو الخطاف اللاحق:

#!/bin/sh
git reset --hard HEAD
echo "Changes pushed to server."
هل كانت مفيدة؟

المحلول

إجابة سؤالك هنا: http://toroid.org/ams/git-website-howto

باختصار ، ما تريد القيام به هو إضافة "شجرة عمل منفصلة" إلى المستودع العاري. عادة تفكر في شجرة عملك على أنها تحتوي على .git الدليل. لا تملك المستودعات العارية شجرة عمل بحكم التعريف ، ولكن يمكنك إنشاء واحدة طالما أنها في دليل مختلف عن الريبو العاري.

الخطاف اللاحق هو مجرد بسيط git checkout -f لتكرار المستودع HEAD في دليل العمل. يستخدم Apache ذلك كجذر المستند الخاص به ، وأنت جميعًا تم تعيينك. في أي وقت تدفعه إلى المستودع العاري ، سيبدأ Apache على الفور في تقديمه.

أستخدم هذا عمومًا للدفع تلقائيًا إلى خادم التدريج لمعرفة ما إذا كانت البيئة "الحقيقية" ستقوم بتقييم التغييرات الخاصة بي. يعد الانتشار إلى الخادم المباشر قصة مختلفة تمامًا. :-)

نصائح أخرى

تحديث مارس 2015

كما ذكرت في "ما هي رسالة تحذير GIT عند الضغط على التغييرات إلى مستودع عن بُعد؟"، يمكنك في الواقع الدفع مباشرة إلى ريبو غير مشترك الآن (Git 2.3.0+ ، فبراير 2015) مع:

git config receive.denyCurrentBranch updateInstead

قم بتحديث شجرة العمل وفقًا لذلك ، ولكن رفض القيام بذلك إذا كان هناك أي تغييرات غير ملتزم بها.

هذا من شأنه أن يسمح لك بتجنب أي خطاف ما بعد الاستقبال.


(الإجابة الأصلية: أكتوبر 2010)

ال gitfaq يوصي ريبو غير بار هذا الخطاف ما بعد التحديث:
(قد يمنحك المزيد من الدلائل حول ما يجري فعليًا في تنفيذ الخطاف. لاحظ أن هذا هو خطاف ما بعد التحديث ، وليس بعد الاستقبال)

#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update".

git-update-server-info

is_bare=$(git-config --get --bool core.bare)

if [ -z "$is_bare" ]
then
    # for compatibility's sake, guess
    git_dir_full=$(cd $GIT_DIR; pwd)
    case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi

update_wc() {
    ref=$1
    echo "Push to checked out branch $ref" >&2
    if [ ! -f $GIT_DIR/logs/HEAD ]
    then
        echo "E:push to non-bare repository requires a HEAD reflog" >&2
        exit 1
    fi
    if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null)
    then
        wc_dirty=0
    else
        echo "W:unstaged changes found in working copy" >&2
        wc_dirty=1
        desc="working copy"
    fi
    if git diff-index --cached HEAD@{1} >/dev/null
    then
        index_dirty=0
    else
        echo "W:uncommitted, staged changes found" >&2
        index_dirty=1
        if [ -n "$desc" ]
        then
            desc="$desc and index"
        else
            desc="index"
        fi
    fi
    if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
    then
        new=$(git rev-parse HEAD)
        echo "W:stashing dirty $desc - see git-stash(1)" >&2
        ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
        git-update-ref --no-deref HEAD HEAD@{1}
        cd $GIT_WORK_TREE
        git stash save "dirty $desc before update to $new";
        git-symbolic-ref HEAD "$ref"
        )
    fi

    # eye candy - show the WC updates :)
    echo "Updating working copy" >&2
    (cd $GIT_WORK_TREE
    git-diff-index -R --name-status HEAD >&2
    git-reset --hard HEAD)
}

if [ "$is_bare" = "false" ]
then
    active_branch=`git-symbolic-ref HEAD`
    export GIT_DIR=$(cd $GIT_DIR; pwd)
    GIT_WORK_TREE=${GIT_WORK_TREE-..}
    for ref
    do
        if [ "$ref" = "$active_branch" ]
        then
            update_wc $ref
        fi
    done
fi

لكي ينجح هذا ، ستظل بحاجة إلى السماح بالتحديد على دفع التغييرات إلى الفرع الحالي باستخدام أي من إعدادات التكوين هذه:

git config receive.denyCurrentBranch ignore

أو

git config receive.denyCurrentBranch warn

كان لي نفس القضية بالضبط. في رد على هذا الرابط: http://toroid.org/ams/git-website-howto - لقد فعل الأمر التالي:

sudo chmod +x hooks/post-receive

لقد فاتنا أ sudo إذن ، قام الإذن أولاً بتكوين الأشياء.

نسخة ثابتة من البرنامج النصي Vonc ، يعمل بالنسبة لي (لا توجد ضمانات على الإطلاق).

#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update".

set -e

git update-server-info

is_bare=$(git config --get --bool core.bare)

if [ -z "${is_bare}" ]
then
    # for compatibility's sake, guess
    git_dir_full=$(cd $GIT_DIR; pwd)
    case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi

update_wc() {
    ref=$1
    echo "Push to checked out branch $ref" >&2
    if [ ! -f ${GIT_DIR}/logs/HEAD ]
    then
        echo "E:push to non-bare repository requires a HEAD reflog" >&2
        exit 1
    fi
    if (cd ${GIT_WORK_TREE}; git diff-files -q --exit-code >/dev/null)
    then
        wc_dirty=0
    else
        echo "W:unstaged changes found in working copy" >&2
        wc_dirty=1
        desc="working copy"
    fi
    if git diff-index --cached HEAD@{1} >/dev/null
    then
        index_dirty=0
    else
        echo "W:uncommitted, staged changes found" >&2
        index_dirty=1
        if [ -n "$desc" ]
        then
            desc="$desc and index"
        else
            desc="index"
        fi
    fi
    if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
    then
        new=$(git rev-parse HEAD)
        echo "W:stashing dirty $desc - see git-stash(1)" >&2
        ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
        git update-ref --no-deref HEAD HEAD@{1}
        cd ${GIT_WORK_TREE}
        git stash save "dirty $desc before update to $new";
        git symbolic-ref HEAD "$ref"
        )
    fi

    # eye candy - show the WC updates :)
    echo "Updating working copy" >&2
    (cd ${GIT_WORK_TREE}
    git diff-index -R --name-status HEAD >&2
    git reset --hard HEAD
    # need to touch some files or restart the application? do that here:
    # touch *.wsgi
    )

}

if [ x"${is_bare}" = x"false" ]
then
    active_branch=$(git symbolic-ref HEAD)
    export GIT_DIR=$(cd ${GIT_DIR}; pwd)
    GIT_WORK_TREE="${GIT_DIR}/.."
    for ref in $(cat)
    do
        if [ x"$ref" = x"${active_branch}" ]
        then
            update_wc $ref
        fi
    done
fi

نص بسيط لإعداد هذا النشر GIT:

تحضير خطاف ما بعد الاستقبال:

echo '#!/bin/sh'        >  .git/hooks/post-receive
echo 'git checkout -f'  >> .git/hooks/post-receive
echo 'git reset --hard' >> .git/hooks/post-receive
chmod +x .git/hooks/post-receive

السماح بدفع هذا المستودع ، على الرغم من أنه ليس عاريًا:

git config receive.denycurrentbranch false

أنا مجرد تخمين ، لكن هذا قد يكون مشكلة في الإذن (المسار الكامل المطلوب؟ cd؟). تحقق من ما يحدث بالفعل في ملفات السجل.

ومع ذلك ، فإن نشر الملفات عبر GIT هو دائمًا مجرد مهام واحدة لعملية النشر. عادة ما تحتاج إلى نسخ بعض الملفات ، وحذف آخر ، والإعداد ، وتحديث أذونات ، وإنشاء مستندات ، إلخ.

للحصول على حل معقد ، قد يكون البرنامج النصي بناء أفضل من أي خطاف Git. الأدوات التي يمكنها التعامل مع هذه المهام بشكل جيد للغاية:

(أدرك أن هذا ليس هو الإجابة التي تتوقعها ، لكن الوقت طويل جدًا لنشره كتعليق)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top