Có thể triển khai một trang web bằng cách sử dụng git push
? Tôi có linh cảm nó có liên quan đến việc sử dụng git hook để thực hiện một git reset --hard
phía máy chủ, nhưng tôi sẽ làm thế nào để hoàn thành việc này?
Có thể triển khai một trang web bằng cách sử dụng git push
? Tôi có linh cảm nó có liên quan đến việc sử dụng git hook để thực hiện một git reset --hard
phía máy chủ, nhưng tôi sẽ làm thế nào để hoàn thành việc này?
Câu trả lời:
Tôi tìm thấy kịch bản này trên trang web này và nó dường như hoạt động khá tốt.
Trên bản sao cục bộ của bạn, sửa đổi tệp .git / config của bạn và thêm máy chủ web của bạn dưới dạng từ xa:
[remote "production"]
url = username@webserver:/path/to/htdocs/.git
Trên máy chủ, thay thế .git / hook / post-update bằng tệp này (trong câu trả lời bên dưới)
Thêm quyền truy cập thực thi vào tệp (một lần nữa, trên máy chủ):
chmod +x .git/hooks/post-update
Bây giờ, chỉ cần đẩy cục bộ đến máy chủ web của bạn và nó sẽ tự động cập nhật bản sao làm việc:
git push production
Sử dụng tệp sau cập nhật bên dưới:
Trên bản sao cục bộ của bạn, sửa đổi tệp .git / config của bạn và thêm máy chủ web của bạn dưới dạng từ xa:
[remote "production"]
url = username@webserver:/path/to/htdocs/.git
Trên máy chủ, thay thế .git / hook / post-update bằng tệp bên dưới
Thêm quyền truy cập thực thi vào tệp (một lần nữa, trên máy chủ):
chmod +x .git/hooks/post-update
Bây giờ, chỉ cần đẩy cục bộ đến máy chủ web của bạn và nó sẽ tự động cập nhật bản sao làm việc:
git push production
#!/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
Sau nhiều lần khởi động sai và kết thúc, cuối cùng tôi cũng có thể triển khai mã trang web chỉ bằng "git đẩy từ xa " nhờ vào bài viết này .
Kịch bản hậu cập nhật của tác giả chỉ dài một dòng và giải pháp của anh ta không yêu cầu cấu hình .htaccess để ẩn repo Git như một số người khác làm.
Một vài vấp ngã nếu bạn triển khai điều này trên phiên bản Amazon EC2;
1) Nếu bạn sử dụng sudo để tạo kho lưu trữ đích trống, bạn phải thay đổi chủ sở hữu của repo thành người dùng ec2 nếu không việc đẩy sẽ thất bại. (Hãy thử "chown ec2-user: ec2-user repo .")
2) Việc đẩy sẽ thất bại nếu bạn không định cấu hình trước vị trí của khóa amazon-private-key .pem của bạn, trong / etc / ssh / ssh_config dưới dạng tham số IdentityFile hoặc trong ~ / .ssh / config bằng cách sử dụng "[ Máy chủ] - HostName - IdentityFile - Bố cục "người dùng" được mô tả tại đây ...
... TUY NHIÊN nếu Host được cấu hình trong ~ / .ssh / config và khác với HostName, việc đẩy Git sẽ thất bại. (Đó có lẽ là một lỗi Git)
không cài đặt git trên máy chủ hoặc sao chép thư mục .git ở đó. để cập nhật máy chủ từ bản sao git, bạn có thể sử dụng lệnh sau:
git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project
bạn có thể phải xóa các tập tin đã bị xóa khỏi dự án.
Điều này sao chép tất cả các kiểm tra trong các tập tin. rsync sử dụng ssh được cài đặt trên máy chủ.
Càng ít phần mềm bạn đã cài đặt trên máy chủ thì anh ta càng an toàn và càng dễ quản lý cấu hình và tài liệu của nó. cũng không cần phải giữ một bản sao git hoàn chỉnh trên máy chủ. nó chỉ làm cho nó phức tạp hơn để bảo đảm mọi thứ đúng cách.
Về bản chất tất cả những gì bạn cần làm là như sau:
server = $1
branch = $2
git push $server $branch
ssh <username>@$server "cd /path/to/www; git pull"
Tôi có những dòng trong ứng dụng của tôi như là một thực thi được gọi deploy
.
vì vậy khi tôi muốn triển khai tôi gõ ./deploy myserver mybranch
.
ssh -A ...
git pull
Nên tránh sử dụng để triển khai tự động vì phần hợp nhất của nó có thể yêu cầu dọn dẹp thủ công nếu có bất kỳ xung đột nào.
Cách tôi làm là tôi có một kho Git trống trên máy chủ triển khai của mình, nơi tôi đẩy các thay đổi. Sau đó, tôi đăng nhập vào máy chủ triển khai, thay đổi thư mục tài liệu của máy chủ web thực tế và thực hiện thao tác git. Tôi không sử dụng bất kỳ móc nào để cố gắng làm điều này tự động, điều đó có vẻ rắc rối hơn giá trị của nó.
git reset
để di chuyển trở lại trong số các thay đổi mới nhất (tất cả các cam kết, không chỉ toàn bộ kéo). Nếu bạn cần khôi phục một cái gì đó cụ thể không phải là cam kết mới nhất, thì bạn có thể sử dụng git revert
nhưng có lẽ chỉ nên sử dụng trong trường hợp khẩn cấp ( git revert
tạo ra một cam kết mới làm mất tác dụng của một số cam kết trước đó).
git config --local receive.denyCurrentBranch updateInstead
Đã thêm vào Git 2.3, đây có thể là một khả năng tốt: https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155
Bạn đặt nó trên kho lưu trữ của máy chủ và nó cũng cập nhật cây làm việc nếu nó sạch.
Đã có những cải tiến hơn nữa trong 2.4 với việc push-to-checkout
móc và xử lý các nhánh chưa sinh .
Sử dụng mẫu:
git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead
cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master
cd ../server
ls
Đầu ra:
a
b
Điều này có những thiếu sót sau đây được đề cập trong thông báo GitHub :
Nhưng tất cả những điểm đó nằm ngoài phạm vi của Git và phải được chăm sóc bởi mã bên ngoài. Vì vậy, theo nghĩa đó, điều này, cùng với móc Git, là giải pháp tối ưu.
Cập nhật: Tôi hiện đang sử dụng giải pháp Lloyd Moore với tác nhân chính ssh -A ...
. Đẩy vào một repo chính và sau đó kéo song song từ tất cả các máy của bạn nhanh hơn một chút và yêu cầu ít thiết lập hơn trên các máy đó.
Không thấy giải pháp này ở đây. chỉ cần đẩy qua ssh nếu git được cài đặt trên máy chủ.
Bạn sẽ cần mục sau đây trong .git / config cục bộ của bạn
[remote "amazon"]
url = amazon:/path/to/project.git
fetch = +refs/heads/*:refs/remotes/amazon/*
Nhưng này, cái gì vậy amazon:
? Trong địa phương ~ / .ssh / config, bạn sẽ cần thêm mục sau:
Host amazon
Hostname <YOUR_IP>
User <USER>
IdentityFile ~/.ssh/amazon-private-key
bây giờ bạn có thể gọi
git push amazon master
ssh <USER>@<YOUR_IP> 'cd /path/to/project && git pull'
(BTW: /path/to/project.git khác với thư mục / đường dẫn / đến / dự án làm việc thực tế)
Trong kịch bản của chúng tôi, chúng tôi đang lưu trữ mã trên github / bitbucket và muốn triển khai đến các máy chủ trực tiếp. Trong trường hợp này, sự kết hợp sau đây hoạt động với chúng tôi (đó là một bản phối lại của các câu trả lời được đánh giá cao ở đây) :
.git
thư mục của bạn vào máy chủ web của bạngit remote add live ssh://user@host:port/folder
git config receive.denyCurrentBranch ignore
Trên điều khiển từ xa: nano .git/hooks/post-receive
và thêm nội dung này:
#!/bin/sh
GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f
Trên điều khiển từ xa: chmod +x .git/hooks/post-receive
git push live
Nếu .git
thư mục của bạn nằm trong tài liệu gốc, hãy đảm bảo bạn ẩn nó từ bên ngoài bằng cách thêm vào .htaccess
( nguồn ):
RedirectMatch 404 /\..*$
Chúng tôi sử dụng capistrano để quản lý triển khai. Chúng tôi xây dựng capistrano để triển khai trên máy chủ dàn dựng và sau đó chạy rsync với tất cả máy chủ của chúng tôi.
cap deploy
cap deploy:start_rsync (when the staging is ok)
Với capistrano, chúng tôi có thể thực hiện khôi phục dễ dàng trong trường hợp có lỗi
cap deploy:rollback
cap deploy:start_rsync
Giddyup là các móc git không cần ngôn ngữ chỉ cần thêm ngôn ngữ để tự động hóa việc triển khai thông qua git đẩy. Nó cũng cho phép bạn có các móc bắt đầu / dừng tùy chỉnh để khởi động lại máy chủ web, làm nóng bộ đệm, v.v.
https://github.com/mpalmer/giddyup
Kiểm tra các ví dụ .
Bạn có thể hình dung ra một git hook mà khi nói một cam kết được thực hiện để nói nhánh "ổn định", nó sẽ kéo các thay đổi và áp dụng chúng vào trang web PHP. Nhược điểm lớn là bạn sẽ không có nhiều quyền kiểm soát nếu có sự cố xảy ra và nó sẽ thêm thời gian vào thử nghiệm của bạn - nhưng bạn có thể biết được sẽ có bao nhiêu công việc sẽ tham gia khi bạn hợp nhất nói chi nhánh của bạn vào nhánh ổn định để biết có bao nhiêu xung đột bạn có thể gặp phải. Điều quan trọng là phải theo dõi bất kỳ tệp nào là trang web cụ thể (ví dụ: tệp cấu hình) trừ khi bạn chỉ có ý định chỉ chạy một trang web.
Thay vào đó, bạn đã xem xét việc thay đổi trang web thay thế?
Để biết thông tin về git hook, xem tài liệu của githooks .
Tôi đưa vào giải pháp Kitô hữu .
git archive --prefix=deploy/ master | tar -x -C $TMPDIR | rsync $TMPDIR/deploy/ --copy-links -av username@server.com:/home/user/my_app && rm -rf $TMPDIR/deploy
Tôi đang sử dụng giải pháp sau đây của toroid.org , có tập lệnh hook đơn giản hơn.
trên máy chủ:
$ mkdir website.git && cd website.git
$ git init --bare
Initialized empty Git repository in /home/ams/website.git/
và cài đặt hook trên máy chủ:
$ mkdir /var/www/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f
GIT_WORK_TREE=/var/www/www git clean -f -d # clean directory from removed files
$ chmod +x hooks/post-receive
trên khách hàng của bạn:
$ mkdir website && cd website
$ git init
Initialized empty Git repository in /home/ams/website/.git/
$ echo 'Hello, world!' > index.html
$ git add index.html
$ git commit -q -m "The humble beginnings of my web site."
$ git remote add web ssh://server.example.org/home/ams/website.git
$ git push web +master:refs/heads/master
sau đó để xuất bản, chỉ cần gõ
$ git push web
Có một mô tả đầy đủ trên trang web: http://toroid.org/ams/git-website-howto
git push web +master:refs/heads/master
thay vì chỉ git push web master
?
Như câu trả lời bổ sung, tôi muốn đưa ra một giải pháp thay thế. Tôi đang sử dụng git-ftp và nó hoạt động tốt.
https://github.com/git-ftp/git-ftp
Dễ sử dụng, chỉ gõ:
git ftp push
và git sẽ tự động tải lên các tập tin dự án.
Trân trọng
Với một môi trường nơi bạn có nhiều nhà phát triển truy cập vào cùng một kho lưu trữ, các nguyên tắc sau có thể giúp ích.
Đảm bảo rằng bạn có một nhóm unix mà tất cả các nhà phát triển thuộc về và trao quyền sở hữu kho lưu trữ .git cho nhóm đó.
Trong .git / config của kho lưu trữ máy chủ, sharedreposeective = true. (Điều này nói với git để cho phép nhiều người dùng cần thiết cho các cam kết và triển khai.
đặt ô của mỗi người dùng trong các tệp bashrc của họ giống nhau - 002 là một khởi đầu tốt
Cuối cùng tôi đã tạo ra công cụ triển khai thô sơ của riêng mình, nó sẽ tự động kéo xuống các bản cập nhật mới từ repo - https://github.com/jesalg/SlimJim - Về cơ bản, nó lắng nghe hook-post-hook-hook của github và sử dụng proxy để kích hoạt cập nhật kịch bản.
Tôi sử dụng hai giải pháp cho hook sau nhận:
GIẢI PHÁP NÂNG CẤP 1
#!/bin/bash
# /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 1
export GIT_DIR=/git/repo-bare.git
export GIT_BRANCH1=master
export GIT_TARGET1=/var/www/html
export GIT_BRANCH2=dev
export GIT_TARGET2=/var/www/dev
echo "GIT DIR: $GIT_DIR/"
echo "GIT TARGET1: $GIT_TARGET1/"
echo "GIT BRANCH1: $GIT_BRANCH1/"
echo "GIT TARGET2: $GIT_TARGET2/"
echo "GIT BRANCH2: $GIT_BRANCH2/"
echo ""
cd $GIT_DIR/
while read oldrev newrev refname
do
branch=$(git rev-parse --abbrev-ref $refname)
BRANCH_REGEX='^${GIT_BRANCH1}.*$'
if [[ $branch =~ $BRANCH_REGEX ]] ; then
export GIT_WORK_TREE=$GIT_TARGET1/.
echo "Checking out branch: $branch";
echo "Checking out to workdir: $GIT_WORK_TREE";
git checkout -f $branch
fi
BRANCH_REGEX='^${GIT_BRANCH2}.*$'
if [[ $branch =~ $BRANCH_REGEX ]] ; then
export GIT_WORK_TREE=$GIT_TARGET2/.
echo "Checking out branch: $branch";
echo "Checking out to workdir: $GIT_WORK_TREE";
git checkout -f $branch
fi
done
GIẢI PHÁP NÂNG CẤP 2
#!/bin/bash
# /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 2
export GIT_DIR=/git/repo-bare.git
export GIT_BRANCH1=master
export GIT_TARGET1=/var/www/html
export GIT_BRANCH2=dev
export GIT_TARGET2=/var/www/dev
export GIT_TEMP_DIR1=/tmp/deploy1
export GIT_TEMP_DIR2=/tmp/deploy2
echo "GIT DIR: $GIT_DIR/"
echo "GIT TARGET1: $GIT_TARGET1/"
echo "GIT BRANCH1: $GIT_BRANCH1/"
echo "GIT TARGET2: $GIT_TARGET2/"
echo "GIT BRANCH2: $GIT_BRANCH2/"
echo "GIT TEMP DIR1: $GIT_TEMP_DIR1/"
echo "GIT TEMP DIR2: $GIT_TEMP_DIR2/"
echo ""
cd $GIT_DIR/
while read oldrev newrev refname
do
branch=$(git rev-parse --abbrev-ref $refname)
BRANCH_REGEX='^${GIT_BRANCH1}.*$'
if [[ $branch =~ $BRANCH_REGEX ]] ; then
export GIT_WORK_TREE=$GIT_TARGET1/.
echo "Checking out branch: $branch";
echo "Checking out to workdir: $GIT_WORK_TREE";
# DEPLOY SOLUTION 2:
cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR1;
export GIT_WORK_TREE=$GIT_TEMP_DIR1/.
git checkout -f $branch
export GIT_WORK_TREE=$GIT_TARGET1/.
rsync $GIT_TEMP_DIR1/. -v -q --delete --delete-after -av $GIT_TARGET1/.
rm -rf $GIT_TEMP_DIR1
fi
BRANCH_REGEX='^${GIT_BRANCH2}.*$'
if [[ $branch =~ $BRANCH_REGEX ]] ; then
export GIT_WORK_TREE=$GIT_TARGET2/.
echo "Checking out branch: $branch";
echo "Checking out to workdir: $GIT_WORK_TREE";
# DEPLOY SOLUTION 2:
cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR2;
export GIT_WORK_TREE=$GIT_TEMP_DIR2/.
git checkout -f $branch
export GIT_WORK_TREE=$GIT_TARGET2/.
rsync $GIT_TEMP_DIR2/. -v -q --delete --delete-after -av $GIT_TARGET2/.
rm -rf $GIT_TEMP_DIR2
fi
done
Cả hai giải pháp đều dựa trên các giải pháp trước đó có sẵn trong chủ đề này.
Lưu ý, BRANCH_REGEX = '^ $ {GIT_BRANCH1}. Các bộ lọc $ 'cho các tên nhánh khớp với chuỗi "master " hoặc "dev *" và triển khai cây công việc, nếu nhánh được đẩy khớp. Điều này giúp có thể triển khai phiên bản dev và phiên bản chính đến các địa điểm khác nhau.
GIẢI PHÁP NÂNG CẤP 1 chỉ xóa các tệp, là một phần của repo và đã bị xóa bởi một cam kết. Nó nhanh hơn Giải pháp triển khai 2.
GIẢI PHÁP DEPLOY 2 có lợi thế, nó sẽ xóa bất kỳ tệp mới nào khỏi thư mục sản xuất, được thêm vào phía máy chủ, bất kể nó có được thêm vào repo hay không. Nó sẽ luôn luôn sạch dupe của repo. Nó chậm hơn Giải pháp triển khai 1.