ปรับใช้โครงการโดยใช้ Git push


412

เป็นไปได้git pushหรือไม่ที่จะปรับใช้เว็บไซต์โดยใช้? ฉันมีเรื่องลางสังหรณ์เกี่ยวกับการใช้git hooksเพื่อทำgit reset --hardบนฝั่งเซิร์ฟเวอร์ แต่ฉันจะทำอย่างไรให้สำเร็จ


2
ฉันเดาว่าสิ่งนี้จะใช้ได้เฉพาะในสถานการณ์ที่มีเซิร์ฟเวอร์ผลิตเพียงเซิร์ฟเวอร์เดียวใช่มั้ย
Rijk

6
@Rijk คุณสามารถผลักดันไปยังเซิร์ฟเวอร์หลายเครื่องพร้อมกันด้วย Git แต่เมื่อคุณถึงระดับนั้นคุณอาจต้องการทางออกที่แท้จริงไม่ใช่แฮ็คแบบนี้
Kyle Cronin

ฉันประสบความสำเร็จในการใช้capistranoกับโครงการของฉันซึ่งแม้ว่าเดิมได้รับการออกแบบมาสำหรับการปรับใช้แอปพลิเคชัน Ruby on Rails ทำงานได้ดีกับ PHP และโครงการอื่น ๆ

แปลคำตอบเป็นภาษารัสเซียใน ru.so: ru.stackoverflow.com/questions/428483/…
Nick Volynkin

คำตอบ:


287

ผมพบว่าสคริปต์นี้บนเว็บไซต์นี้และดูเหมือนว่าจะทำงานได้ค่อนข้างดี

  1. คัดลอกไปที่ไดเรกทอรี. git ของคุณไปยังเว็บเซิร์ฟเวอร์ของคุณ
  2. บนโลคัลสำเนาของคุณให้แก้ไขไฟล์. git / config ของคุณและเพิ่มเว็บเซิร์ฟเวอร์เป็นรีโมต:

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. บนเซิร์ฟเวอร์ให้แทนที่. git / hooks / post-update ด้วยไฟล์นี้ (ในคำตอบด้านล่าง)

  4. เพิ่มการเข้าถึงเพื่อเรียกใช้งานไฟล์ (อีกครั้งบนเซิร์ฟเวอร์):

    chmod +x .git/hooks/post-update
    
  5. ตอนนี้เพียงกดไปที่เว็บเซิร์ฟเวอร์ของคุณและควรอัปเดตสำเนาการทำงานโดยอัตโนมัติ:

    git push production
    

128
ตรวจสอบให้แน่ใจว่าคุณมีนโยบาย. htaccess ที่ป้องกันไม่ให้อ่านไดเรกทอรี. git ใครบางคนที่รู้สึกเหมือนดำน้ำ URL อาจมีวันฟิลด์พร้อมรหัสแหล่งที่มาทั้งหมดหากสามารถเข้าถึงได้
Jeff Ferland

39
หรือทำให้ไดเรกทอรีสาธารณะเป็นไดเรกทอรีย่อยของ git repo จากนั้นคุณสามารถมีไฟล์ส่วนตัวที่คุณมั่นใจได้ว่าจะไม่ถูกเปิดเผยต่อสาธารณะ
tlrobinson

3
ลิงค์นี้ตาย มีลิงค์อื่นไปยังไฟล์ post-update หรือไม่
Robert Hurst

6
บางทีฉันอาจจะขาดอะไรบางอย่างไป แต่คุณไม่ต้องการให้เซิร์ฟเวอร์การผลิตของคุณดึงออกมาจากที่เก็บข้อมูลหลัก git repository ของ producttion branch ฉันเดาว่า OP มีแค่เซิร์ฟเวอร์เดียว? ฉันมักจะทำให้เซิร์ฟเวอร์การรวมต่อเนื่องของฉันทำการปรับใช้ไซต์ของฉัน (ใช้การทดสอบบางอย่างก่อนการปรับใช้)
Adam Gent

4
ทำตามขั้นตอนเหล่านั้นจากที่เก็บที่มีลำดับการคอมมิทอยู่แล้ว ในตอนแรกคุณไม่สามารถผลักดันได้เนื่องจากสาขาหลักได้ชำระเงินแล้ว จากนั้นถ้าคุณชำระเงินสาขาอื่นในระยะไกลเฉพาะไฟล์ที่แตกต่างกันจะถูกตรวจสอบลงในไดเรกทอรีการทำงาน ฉันคาดว่าเบ็ดจะทำการรีเซ็ต - ยากสำหรับฉัน
barrymac

80

ใช้ไฟล์post-updateด้านล่าง:

  1. คัดลอกไปที่ไดเรกทอรี. git ของคุณไปยังเว็บเซิร์ฟเวอร์ของคุณ
  2. บนโลคัลสำเนาของคุณให้แก้ไขไฟล์. git / config ของคุณและเพิ่มเว็บเซิร์ฟเวอร์เป็นรีโมต:

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. บนเซิร์ฟเวอร์ให้แทนที่. git / hooks / post-update ด้วยไฟล์ด้านล่าง

  4. เพิ่มการเข้าถึงเพื่อเรียกใช้งานไฟล์ (อีกครั้งบนเซิร์ฟเวอร์):

    chmod +x .git/hooks/post-update
    
  5. ตอนนี้เพียงกดไปที่เว็บเซิร์ฟเวอร์ของคุณและควรอัปเดตสำเนาการทำงานโดยอัตโนมัติ:

    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

5
Geez ... เพียงแค่เขียนสคริปต์นี้ในภาษาที่คุณใช้สำหรับการพัฒนาไม่ว่าจะเป็น php, python, groovy หรืออะไรก็ตาม! ฉันไม่เคยเข้าใจความรักนี้สำหรับเชลล์สคริปต์ที่มีซินแท็กซ์ค่อนข้างแปลก ๆ
dVaffection

4
@dVaffection ไม่ว่าในกรณีใดคุณจะเขียนคำสั่งเชลล์ถ้าคุณใช้ git ดังนั้นแทนที่จะเขียนสคริปต์ในภาษาอื่นและเล่นปาหี่อย่างต่อเนื่องระหว่างภาษานั้นกับเชลล์ เขียนมันทั้งหมดในเปลือกดูเหมือนว่าตรรกะคุณไม่คิดเหรอ?
Abderrahmane TAHRI JOUTI

ฉันต้องดำเนินการ 'git config get.denyCurrentBranch updateInstead' บนเซิร์ฟเวอร์ด้วยเพื่อที่จะยอมรับการพุช ฉันคิดว่าเป็นเพราะสาขาเช็คเอาท์?
stackPusher

60

หลังจากลองผิดลองถูกหลายคนและปลายตายฉันในที่สุดก็สามารถที่จะปรับใช้โค้ดของเว็บไซต์ที่มีเพียง "ดันคอมไพล์ระยะไกล " ต้องขอบคุณบทความนี้

สคริปต์หลังการอัปเดตของผู้เขียนมีความยาวเพียงหนึ่งบรรทัดและโซลูชันของเขาไม่ต้องการการกำหนดค่า. htaccess เพื่อซ่อน repo Git เหมือนกับที่คนอื่นทำ

คู่ของบล็อกที่สะดุดถ้าคุณกำลังปรับใช้นี้ในอินสแตนซ์ของ Amazon EC2

1) ถ้าคุณใช้ sudo เพื่อสร้างพื้นที่เก็บข้อมูลปลายทางเปล่าคุณต้องเปลี่ยนเจ้าของ repo เป็นผู้ใช้ ec2 มิเช่นนั้นการกดจะล้มเหลว (ลอง "chown ec2-user: repoผู้ใช้ ec2 ")

2) การพุชจะล้มเหลวหากคุณไม่ได้กำหนดค่าตำแหน่งล่วงหน้าของamazon-private-key .pem ของคุณใน / etc / ssh / ssh_config เป็นพารามิเตอร์ IdentityFile หรือใน ~ / .ssh / config โดยใช้ "[ โฮสต์] - ชื่อโฮสต์ - IdentityFile - โครงร่างผู้ใช้ "อธิบายไว้ที่นี่ ...

... อย่างไรก็ตามหากมีการกำหนดค่าโฮสต์ใน ~ / .ssh / config และแตกต่างจากชื่อโฮสต์การกด Git จะล้มเหลว (นั่นอาจเป็นข้อผิดพลาด Git)


ฉันทำตามขั้นตอนในบทความที่คุณพูดถึงและทุกอย่างทำงานได้อย่างมีเสน่ห์ ฉันสงสัยเพียงว่ามีข้อบกพร่องบางประการเกี่ยวกับความปลอดภัยหรือความมั่นคง คำแนะนำเกี่ยวกับเรื่องนี้?
xlttj

xl-t: สมมติว่าคุณใช้ Git มากกว่า SSH ฉันจะบอกว่าอันตรายอยู่ที่การทำผิดกับ Git คุณสามารถถามผู้เขียนบทความ; เขาลงท้ายด้วย "ยินดีต้อนรับคำถามและคำแนะนำ" กลยุทธ์การจำลองแบบปัจจุบันของฉันคือการใช้ซอฟต์แวร์ส่งผ่านโดย Panic
Earl Zedd

1
บทความที่เชื่อมโยงมีข้อกำหนดสำคัญหนึ่งข้อเมื่อคุณใช้ hooks hooks จะล้มเหลวหาก. git เกิดขึ้นในรูปแบบการตั้งชื่อเช่นเดียวกับไดเรกทอรีทำงาน ie / foo / bar (ไดเรกทอรีทำงาน) และ /foo/bar.git (พื้นที่เก็บข้อมูลแบร์โบนแบร์) ดังนั้นให้แน่ใจว่าคุณเปลี่ยนชื่อ / foo / bar เป็นอย่างอื่นเช่น /foo/bar.live หรือ / foo / blah ดีในกรณีที่คุณสงสัยข้อความข้อผิดพลาดที่แน่นอนที่คุณจะได้รับหากไดเรกทอรีการทำงานของคุณมีชื่อเดียวกันกับ พื้นที่เก็บข้อมูลแบร์โบนคือ "ระยะไกล: ร้ายแรง: ไม่สามารถย้อนกลับไปยัง cwd ดั้งเดิม: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว"
Antony

1
ฉันไม่ทำตามเหตุผลที่คุณต้องใช้การติดตั้ง post เพื่อให้ทำงานได้ การผลักดันการเปลี่ยนรหัสไปยัง repo ระยะไกลหมายความว่า repo ระยะไกลเป็นรุ่นล่าสุด ฉันพลาดอะไรไป
Charlie Schliesser

1
@CharlieS สิ่งที่คุณขาดไปก็คือคอมไพล์จะไม่ยอมให้คุณดันสาขาไปยังที่เก็บที่สาขานั้นเช็คเอาท์ ในกรณีนี้คำตอบ (IMHO ดีมาก) คือการมีสองที่เก็บ: repo เปลือยที่คุณผลักดันและ repo ที่สองซึ่งมีการปรับปรุงไดเรกทอรีการทำงานผ่านเบ็ดเมื่อ repo เปลือยถูกผลักไป
Ben Hughes

21

อย่าติดตั้งคอมไพล์บนเซิร์ฟเวอร์หรือคัดลอกโฟลเดอร์. git ที่นั่น เพื่ออัปเดตเซิร์ฟเวอร์จาก git clone คุณสามารถใช้คำสั่งต่อไปนี้:

git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project

คุณอาจต้องลบไฟล์ที่ถูกลบออกจากโครงการ

นี่เป็นการคัดลอกไฟล์ที่เช็คอินทั้งหมด rsync ใช้ ssh ซึ่งติดตั้งบนเซิร์ฟเวอร์อย่างไรก็ตาม

ยิ่งคุณติดตั้งซอฟต์แวร์บนเซิร์ฟเวอร์น้อยลงเท่าไหร่ก็ยิ่งมีความปลอดภัยมากขึ้นและจัดการการกำหนดค่าและจัดการเอกสารได้ง่ายขึ้น นอกจากนี้ยังไม่จำเป็นต้องเก็บโคลนคอมไพล์อย่างสมบูรณ์บนเซิร์ฟเวอร์ มันทำให้ซับซ้อนมากขึ้นเพื่อรักษาความปลอดภัยทุกอย่างอย่างถูกต้อง


3
หนึ่งข้อแม้: มันจะซิงค์ไฟล์ที่คุณมีในไดเรกทอรีการทำงานของคุณ ฉันคิดว่ามันสามารถหลีกเลี่ยงได้โดยใช้สคริปต์ที่หยุดการเปลี่ยนแปลงในปัจจุบันทำความสะอาดทุกอย่างปรับใช้แล้วเปลี่ยนกลับการซ่อน
mateusz.fiolka

เซิร์ฟเวอร์เป็นเพศชายหรือไม่
Ian Warburton

12

สิ่งสำคัญที่คุณต้องทำมีดังต่อไปนี้:

server = $1
branch = $2
git push $server $branch
ssh <username>@$server "cd /path/to/www; git pull"

ฉันมีบรรทัดเหล่านั้นในแอปพลิเคชันของฉันซึ่งเรียกใช้งานdeployได้

./deploy myserver mybranchดังนั้นเมื่อผมต้องการจะปรับประเภท


ดูคำตอบของฉันวิธีการแก้ปัญหาหากคุณต้องการรหัสส่วนตัวที่แตกต่างกันหรือชื่อผู้ใช้สำหรับ ssh
Karussell

โซลูชันนี้เร็วกว่าของฉันเมื่อปรับใช้กับเซิร์ฟเวอร์หลายเครื่อง! เพียงแค่กดไปที่ repo หลักและดึงขนานจากนั้น และถ้าคุณไม่ต้องการหรือไม่สามารถปรับใช้คีย์ของคุณให้กับทุกอินสแตนซ์ให้ใช้คีย์เอเจนต์! ssh -A ...
Karussell

1
มันจะง่ายขึ้นถ้าคุณรวมคำแนะนำเกี่ยวกับการตั้งค่าคีย์ SSH ซึ่งคำตอบนี้ต้องอาศัยการทำงานแบบ 'ต่อเนื่อง'
Hengjie

การใช้git pullควรหลีกเลี่ยงสำหรับการใช้งานโดยอัตโนมัติเพราะเป็นส่วนหนึ่งของการผสานก็อาจจำเป็นต้องมีการทำความสะอาดด้วยตนเองหากมีความขัดแย้งใด ๆ
Quinn Comendant

9

วิธีที่ฉันทำคือฉันมีที่เก็บ Git เปลือยบนเซิร์ฟเวอร์การปรับใช้ของฉันที่ฉันผลักดันการเปลี่ยนแปลง จากนั้นฉันล็อกอินเข้าสู่เซิร์ฟเวอร์การปรับใช้เปลี่ยนเป็นไดเรกทอรีเอกสารเว็บเซิร์ฟเวอร์จริงและทำ git pull ฉันไม่ใช้ hooks ใด ๆ เพื่อพยายามทำสิ่งนี้โดยอัตโนมัติดูเหมือนว่าจะมีปัญหามากกว่าที่ควรค่า


ในกรณีที่มีข้อผิดพลาดในรหัสใหม่คุณรีเซ็ตต่อการกระทำหรือดึงทั้งหมด? (หรือเป็นไปได้เพียง 1 ข้อเท่านั้น)
Rudie

1
@Rudie: หากคุณต้องการย้อนกลับการเปลี่ยนแปลงในเซิร์ฟเวอร์การปรับใช้คุณสามารถใช้git resetเพื่อย้ายกลับไปมาระหว่างการเปลี่ยนแปลงล่าสุด (ทุกการกระทำไม่ใช่แค่การดึงทั้งหมด) หากคุณต้องการย้อนกลับสิ่งที่เฉพาะเจาะจงที่ไม่ใช่การคอมมิทล่าสุดคุณสามารถใช้git revertแต่ควรใช้ในกรณีฉุกเฉินเท่านั้น ( git revertสร้างคอมมิชชันใหม่ที่ยกเลิกผลกระทบของการคอมมิชชันก่อนหน้านี้)
เกร็กฮิวกิล

แค่อยากรู้อยากเห็น: ทำไมคุณคิดว่า hooks จะเป็นปัญหามากกว่าที่ควรจะเป็น
Rijk

@Rijk: เมื่อใช้ hooks สำหรับสิ่งนี้ไดเรกทอรีเอกสารเว็บเซิร์ฟเวอร์จริงจะเปลี่ยนไปโดยกระบวนการพื้นหลังอัตโนมัติ การเข้าสู่ระบบช่วยให้ฉันสามารถควบคุมได้มากขึ้นเมื่อมีการเปลี่ยนแปลงกับไดเรกทอรีเอกสาร นอกจากนี้ยังง่ายต่อการแก้ไขเมื่อสิ่งผิดปกติ ฮุกอาจเหมาะสมกว่านี้หากผู้มอบหมายไม่สามารถเข้าสู่เว็บเซิร์ฟเวอร์ได้อย่างเพียงพอ
Greg Hewgill

ดังนั้นโฟลเดอร์ webapp ที่แท้จริงของคุณจึงเป็นที่เก็บ. git โฟลเดอร์. git เกี่ยวกับโลกภายนอกมองเห็นได้อย่างไร
เฟอร์นันโด

9

git config --local receive.denyCurrentBranch updateInstead

เพิ่มใน Git 2.3 นี่อาจเป็นโอกาสดี: https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

คุณตั้งค่าบนพื้นที่เก็บข้อมูลเซิร์ฟเวอร์และยังปรับปรุงต้นไม้การทำงานถ้ามันสะอาด

ได้มีการปรับปรุงต่อไปใน 2.4 กับเบ็ดและการจัดการของสาขาในครรภ์push-to-checkout

ตัวอย่างการใช้งาน:

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

เอาท์พุท:

a
b

สิ่งนี้มีข้อบกพร่องดังต่อไปนี้ที่กล่าวถึงในประกาศ GitHub :

  • เซิร์ฟเวอร์ของคุณจะมีไดเรกทอรี. git ที่มีประวัติทั้งหมดของโครงการของคุณ คุณอาจต้องการตรวจสอบให้แน่ใจเป็นพิเศษว่าผู้ใช้จะไม่สามารถให้บริการได้!
  • ในระหว่างการปรับใช้จะเป็นไปได้ที่ผู้ใช้จะพบไซต์ในสภาวะที่ไม่สอดคล้องกันในบางครั้งโดยมีไฟล์บางไฟล์ในเวอร์ชันเก่าและอื่น ๆ ในเวอร์ชันใหม่หรือแม้กระทั่งไฟล์ที่เขียนครึ่งไฟล์ หากนี่เป็นปัญหาสำหรับโครงการของคุณอาจเป็นไปได้ว่า
  • หากโครงการของคุณต้องการขั้นตอน "สร้าง" คุณจะต้องตั้งค่านั้นอย่างชัดเจนอาจจะผ่าน githooks

แต่คะแนนทั้งหมดเหล่านี้อยู่นอกขอบเขตของ Git และต้องได้รับการดูแลจากโค้ดภายนอก ดังนั้นในแง่นี้สิ่งนี้ร่วมกับ Git hooks จึงเป็นทางออกที่ดีที่สุด


หากต้องการตั้งค่าให้เรียกใช้คำสั่งนี้: 'git config get.denyCurrentBranch updateInstead' ในเทอร์มินัล
stackPusher

5

ปรับปรุง: ตอนนี้ผมใช้ลอยด์มัวssh -A ...แก้ปัญหากับตัวแทนที่สำคัญ ผลักไปที่ repo หลักแล้วดึงมันขนานกับเครื่องทั้งหมดของคุณเร็วขึ้นเล็กน้อยและต้องใช้การตั้งค่าน้อยลงในเครื่องเหล่านั้น


ไม่เห็นโซลูชันนี้ที่นี่ เพียงแค่กดผ่าน ssh หากมีการติดตั้ง git บนเซิร์ฟเวอร์

คุณจะต้องมีรายการต่อไปนี้ใน. git / config ในพื้นที่ของคุณ

[remote "amazon"]
    url = amazon:/path/to/project.git
    fetch = +refs/heads/*:refs/remotes/amazon/*

แต่เฮ้นั่นมันอะไรกันamazon:? ในโลคัล ~ / .ssh / config ของคุณคุณจะต้องเพิ่มรายการต่อไปนี้:

Host amazon
    Hostname <YOUR_IP>
    User <USER>
    IdentityFile ~/.ssh/amazon-private-key

ตอนนี้คุณสามารถโทร

git push amazon master
ssh <USER>@<YOUR_IP> 'cd /path/to/project && git pull'

(BTW: /path/to/project.git แตกต่างจากไดเรกทอรีการทำงาน / เส้นทาง / ไปยัง / โครงการจริง)


5

สำหรับสถานการณ์การปรับใช้

ในสถานการณ์ของเราเรากำลังจัดเก็บรหัสไว้บน github / bitbucket และต้องการปรับใช้กับเซิร์ฟเวอร์ที่ใช้งานจริง ในกรณีนี้ชุดค่าผสมต่อไปนี้ใช้ได้กับเรา(นั่นคือรีมิกซ์ของคำตอบที่ได้รับการโหวตอย่างสูงที่นี่) :

  1. คัดลอก.gitไดเรกทอรีของคุณไปยังเว็บเซิร์ฟเวอร์ของคุณ
  2. บนสำเนาในเครื่องของคุณ git remote add live ssh://user@host:port/folder
  3. บนรีโมท: git config receive.denyCurrentBranch ignore
  4. บนรีโมต: nano .git/hooks/post-receiveและเพิ่มเนื้อหานี้:

    #!/bin/sh GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f

  5. บนรีโมท: chmod +x .git/hooks/post-receive

  6. ตอนนี้คุณสามารถผลักดันด้วย git push live

หมายเหตุ

  • วิธีนี้ใช้ได้กับเวอร์ชั่นคอมไพล์รุ่นเก่า (ทดสอบกับ 1.7 และ 1.9)
  • คุณต้องตรวจสอบให้แน่ใจก่อนที่จะดัน github / bitbucket ก่อนดังนั้นคุณจะมี repo ที่สอดคล้องกันในการถ่ายทอดสด
  • หาก.gitโฟลเดอร์ของคุณอยู่ในรูทเอกสารตรวจสอบให้แน่ใจว่าคุณซ่อนมันจากด้านนอกด้วยการเพิ่ม.htaccess(ที่มา ):

    RedirectMatch 404 /\..*$


4

เราใช้capistranoสำหรับการจัดการการปรับใช้ เราสร้าง capistrano เพื่อปรับใช้บนเซิร์ฟเวอร์ staging แล้วเรียกใช้ rsync กับเซิร์ฟเวอร์ทั้งหมดของเรา

cap deploy
cap deploy:start_rsync (when the staging is ok)

ด้วย capistrano เราสามารถย้อนกลับได้ง่ายในกรณีที่เกิดข้อผิดพลาด

cap deploy:rollback
cap deploy:start_rsync

คุณรวมการใช้งานสดผ่าน rsync ใน capistrano?
Martin Abraham

2

Giddyupเป็นตะขอคอมไพล์เพียงเพิ่มภาษาน้ำไม่เชื่อเรื่องพระเจ้าเพื่อทำการติดตั้งโดยอัตโนมัติผ่านการกด git นอกจากนี้ยังช่วยให้คุณมีตะขอเริ่ม / หยุดที่กำหนดเองสำหรับการรีสตาร์ทเว็บเซิร์ฟเวอร์อุ่นเครื่องแคช ฯลฯ

https://github.com/mpalmer/giddyup

ตรวจสอบตัวอย่าง


1

ดูเหมือนว่าคุณควรมีสำเนาสองชุดบนเซิร์ฟเวอร์ของคุณ สำเนาเปลือยที่คุณสามารถผลักดัน / ดึงซึ่งคุณจะผลักดันการเปลี่ยนแปลงของคุณเมื่อเสร็จแล้วคุณจะคัดลอกสิ่งนี้ลงในสารบบเว็บของคุณและตั้ง cronjob เพื่ออัปเดต git pull จากสารบบเว็บของคุณทุกวันหรือ ดังนั้น.


1

คุณสามารถตั้งค่า git hook ได้ซึ่งเมื่อพูดว่าคอมมิชชันทำเพื่อพูดว่า "เสถียร" สาขามันจะดึงการเปลี่ยนแปลงและนำไปใช้กับไซต์ PHP ข้อเสียใหญ่คือคุณจะไม่สามารถควบคุมได้มากนักหากมีสิ่งผิดปกติและจะเพิ่มเวลาในการทดสอบของคุณ - แต่คุณสามารถทราบได้ว่าจะต้องมีการทำงานมากแค่ไหนเมื่อคุณรวมสาขาของคุณไว้ในสาขามั่นคง วิธีการหลายความขัดแย้งที่คุณอาจทำงานเป็น มันเป็นสิ่งสำคัญที่จะต้องคอยจับตาดูไฟล์ใด ๆ ที่มีเฉพาะไซต์ (เช่นไฟล์กำหนดค่า) เว้นแต่คุณจะตั้งใจที่จะเรียกใช้เพียงไซต์เดียวเท่านั้น

คุณได้มองเข้าไปในการผลักดันการเปลี่ยนแปลงไปยังเว็บไซต์แทน?

สำหรับข้อมูลเกี่ยวกับ git hooks ดูที่เอกสารประกอบของgithooks


1

การใช้วิธีการแก้ปัญหาของคริสเตียน

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
  • เก็บสาขาหลักเป็น tar
  • แตกไฟล์เก็บถาวร tar ลงในการปรับใช้ dir ในโฟลเดอร์ temp ของระบบ
  • rsync เปลี่ยนเป็นเซิร์ฟเวอร์
  • ลบปรับใช้ dir จากโฟลเดอร์ temp

1

ฉันใช้โซลูชันต่อไปนี้โดยtoroid.orgซึ่งมีสคริปต์เบ็ดที่เรียบง่ายกว่า

บนเซิร์ฟเวอร์:

$ mkdir website.git && cd website.git
$ git init --bare
Initialized empty Git repository in /home/ams/website.git/

และติดตั้ง hook บนเซิร์ฟเวอร์:

$ 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

ลูกค้าของคุณ:

$ 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

จากนั้นเพื่อเผยแพร่เพียงพิมพ์

$ git push web

มีคำอธิบายแบบเต็มบนเว็บไซต์: http://toroid.org/ams/git-website-howto


วิธีนี้จะไม่ลบไฟล์ที่มีอยู่ในที่เก็บ
RusAlex

2
ทำไมgit push web +master:refs/heads/masterแทนที่จะเป็นแค่git push web master?
Matthieu Moy

1

ในฐานะที่เป็นคำตอบที่สมบูรณ์ฉันต้องการที่จะเสนอทางเลือกอื่น ฉันใช้ git-ftp และใช้งานได้ดี

https://github.com/git-ftp/git-ftp

ใช้งานง่ายเพียงพิมพ์:

git ftp push

และคอมไพล์จะอัปโหลดไฟล์โครงการโดยอัตโนมัติ

ความนับถือ


0

กำหนดสภาพแวดล้อมที่คุณมีนักพัฒนาหลายคนเข้าถึงที่เก็บเดียวกันแนวทางต่อไปนี้อาจช่วยได้

ตรวจสอบให้แน่ใจว่าคุณมีกลุ่ม unix ที่ devs ทั้งหมดเป็นเจ้าของและมอบสิทธิ์การเป็นเจ้าของพื้นที่เก็บข้อมูล. git ให้กับกลุ่มนั้น

  1. ใน. git / config ของที่เก็บเซิร์ฟเวอร์ชุด sharedrepository = true (สิ่งนี้บอกให้คอมไพล์อนุญาตผู้ใช้หลายคนซึ่งจำเป็นสำหรับการคอมมิทและการปรับใช้

  2. ตั้ง umask ของผู้ใช้แต่ละคนในไฟล์ bashrc ของพวกเขาให้เหมือนกัน - 002 เป็นการเริ่มต้นที่ดี


0

ฉันลงเอยด้วยการสร้างเครื่องมือการปรับใช้พื้นฐานของฉันเองซึ่งจะดึงการอัปเดตใหม่จาก repo โดยอัตโนมัติ - https://github.com/jesalg/SlimJim - โดยทั่วไปจะฟัง github post-receive-hook และใช้พร็อกซีเพื่อเรียก อัปเดตสคริปต์


0

ฉันใช้สองวิธีแก้ไขสำหรับการขอ post:

โซลูชั่น DEPLOY 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

โซลูชัน DEPLOY 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

โซลูชันทั้งสองนั้นใช้วิธีแก้ไขปัญหาก่อนหน้านี้ในหัวข้อนี้

หมายเหตุ BRANCH_REGEX = '^ $ {GIT_BRANCH1} $ 'ตัวกรองสำหรับชื่อสาขาที่ตรงกับสตริง"master " หรือ "dev *" และปรับใช้แผนผังการทำงานหากสาขาที่ถูกพุชตรงกัน สิ่งนี้ทำให้เป็นไปได้ในการปรับใช้รุ่น dev และเวอร์ชันหลักไปยังสถานที่ที่แตกต่างกัน

DEPLOY SOLUTION 1 จะลบเฉพาะไฟล์ซึ่งเป็นส่วนหนึ่งของ repo และถูกลบโดยคอมมิชชัน มันเร็วกว่า Deployment Solution 2

DEPLOY SOLUTION 2 มีข้อดีคือมันจะลบไฟล์ใหม่ใด ๆ ออกจากไดเรกทอรีการผลิตซึ่งถูกเพิ่มเข้าไปในฝั่งเซิร์ฟเวอร์ไม่ว่าจะถูกเพิ่มลงใน repo หรือไม่ มันจะทำความสะอาด repe ของ repo เสมอ ช้ากว่า Deployment Solution 1

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.