อะไรคือ“ git remote add …” และ“ git push origin origin”?


288

บ่อยครั้งที่ Git และ Rails ดูเหมือนเวทมนตร์ ... เช่นในบทแรกของหนังสือ Tutorials 3 ของ Railsมันพูดถึง Git:

git remote add origin git@github.com:peter/first_app.git
git push origin master

และมันก็บอกว่า "ใช้งานได้ดี" โดยไม่ได้พูดอะไรมากและเริ่มพูดคุยเกี่ยวกับการแตกแขนง ค้นหาสุทธิแสดงว่าgit remote addจะเพิ่ม "ชื่อย่อ" เช่นoriginและมันอาจเป็นชื่อใด ๆ เช่นกันซึ่งเป็นเหมือนนามแฝงของ URL และoriginเป็นเส้นทางปกติของที่ repo ระยะไกลชี้ไปที่ (ในhttp://git-scm.com/book/en/Git-Basics-Working-with-Remotesภายใต้ "การเพิ่มที่เก็บระยะไกล")

เหตุใด URL จึงไม่ใช่ git://git@github.com/peter/first_app.gitแต่อยู่ในรูปแบบอื่น - เป็นรูปแบบอะไร ทำไมมันจะต้องจบลงด้วย.git? ฉันพยายามไม่ใช้.gitตอนท้ายและก็ใช้งานได้เช่นกัน หากไม่.gitสามารถมีอะไรอีกบ้าง gitในgit@github.comน่าจะเป็นบัญชีผู้ใช้บนเซิร์ฟเวอร์คอมไพล์หรือไม่

นอกจากนี้ทำไมจึงต้องใช้ verbose มากgit push origin master? ค่าเริ่มต้นไม่สามารถเป็นแหล่งกำเนิดและต้นแบบได้หรือไม่ ฉันพบว่าในครั้งแรกorigin masterจำเป็นต้องมี แต่หลังจากแก้ไขและคอมมิทเล็กน้อยแล้วก็git pushเป็นสิ่งที่ต้องการ (ไม่จำเป็นorigin master) ใครบางคนที่รู้ว่าเกิดอะไรขึ้นจะให้รายละเอียดบ้างไหม?

บางครั้งมันรู้สึกเหมือนเวทมนต์มากมายโดยไม่มีคำอธิบาย ... และบางครั้งคนที่ใช้มันก็มีความมั่นใจมากและเมื่อถูกถามว่าทำไมไม่สามารถอธิบายได้และตอบกลับด้วยบางสิ่งเช่น บางครั้งการปฏิบัติมากและในทางปฏิบัติ มันไม่ได้เลวร้ายที่จะใช้งานได้จริง แต่อาจจะไม่เป็นประโยชน์ในจุดที่ไม่รู้ว่าเกิดอะไรขึ้น

คำตอบ:


344

gitเป็นเหมือน UNIX เป็นมิตรกับผู้ใช้ แต่จู้จี้จุกจิกเกี่ยวกับเพื่อน มันเป็นเรื่องที่ทรงพลังและเป็นมิตรกับผู้ใช้เหมือนกับการวางท่อเปลือก

ดังที่ได้กล่าวไว้เมื่อคุณเข้าใจกระบวนทัศน์และแนวคิดมันมีความชัดเจนแบบเดียวกับที่ฉันคาดหวังจากเครื่องมือบรรทัดคำสั่งของ UNIX คุณควรสละเวลาสักครู่เพื่ออ่านหนึ่งในบทเรียน git ที่ดีมากมายที่มีอยู่ออนไลน์ หนังสือ Pro Git เป็นจุดเริ่มต้นที่ดี

เพื่อตอบคำถามแรกของคุณ

  1. คืออะไร git remote add ...

    อย่างที่คุณอาจจะรู้ว่าgitมันเป็นระบบควบคุมเวอร์ชันแบบกระจาย การดำเนินการส่วนใหญ่จะทำในพื้นที่ ในการติดต่อสื่อสารกับโลกภายนอก, การใช้สิ่งที่เรียกว่าgit remotesนี่คือที่เก็บอื่นนอกเหนือจากที่อยู่บนโลคัลดิสก์ของคุณซึ่งคุณสามารถpushเปลี่ยนเป็น (เพื่อให้คนอื่นเห็นได้) หรือpullจาก (เพื่อให้คุณสามารถรับการเปลี่ยนแปลงอื่น ๆ ) คำสั่งgit remote add origin git@github.com:peter/first_app.gitสร้างระยะไกลใหม่ที่เรียกว่าตั้งอยู่ที่origin git@github.com:peter/first_app.gitเมื่อคุณทำสิ่งนี้ในคำสั่ง push คุณสามารถกดไปที่originแทนที่จะพิมพ์ URL ทั้งหมด

  2. คืออะไร git push origin master

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

ตอนนี้เกี่ยวกับการขนส่ง (เช่นอะไรgit://) หมายถึง URL ที่เก็บระยะไกลอาจมีหลายประเภท ( file://และhttps://อื่น ๆ ) Git นั้นอาศัยกลไกการตรวจสอบความถูกต้องที่จัดทำโดยการขนส่งเพื่อดูแลสิทธิ์และสิ่งของ ซึ่งหมายความว่าสำหรับfile://URL มันจะเป็นการอนุญาตให้ใช้ไฟล์ของ UNIX เป็นต้นgit://แบบแผนนี้ขอให้ git ใช้โปรโตคอลการขนส่งภายในของตัวเอง สำหรับ URL ที่แน่นอนนั้นเป็นวิธีที่เป็นเพราะวิธีที่ github ตั้งค่าgitเซิร์ฟเวอร์

ตอนนี้การใช้คำฟุ่มเฟื่อย คำสั่งที่คุณพิมพ์คือคำสั่งทั่วไป เป็นไปได้ที่จะบอกคอมไพล์เช่น "สาขาที่เรียกmasterตรงนี้คือกระจกท้องถิ่นของสาขาที่เรียกfooบนรีโมตที่เรียกว่าbar" ในพูดคอมไพล์ที่นี้หมายถึงว่าแทร็คmaster bar/fooเมื่อคุณโคลนเป็นครั้งแรกคุณจะได้รับชื่อสาขาmasterและชื่อระยะไกลorigin(ที่คุณโคลน) พร้อมชุดต้นแบบท้องถิ่นเพื่อติดตามต้นแบบที่จุดเริ่มต้น เมื่อตั้งค่านี้แล้วคุณสามารถพูดgit pushและทำมันได้ คำสั่งที่ยาวกว่านั้นมีให้ในกรณีที่คุณต้องการ (เช่นgit pushอาจส่งไปยัง repo สาธารณะอย่างเป็นทางการและgit push review masterสามารถใช้เพื่อผลักดันไปยังรีโมตแยกต่างหากซึ่งทีมของคุณใช้เพื่อตรวจสอบโค้ด) คุณสามารถกำหนดให้สาขาของคุณเป็นสาขาการติดตามโดยใช้--set-upstreamตัวเลือกของgit branchคำสั่ง

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


8
คุณอาจต้องการเพิ่มบันทึกย่อในย่อหน้าของคุณเกี่ยวกับการขนส่งอธิบายว่าgit@github.com:peter/first_app.gitเป็นscpไวยากรณ์รูปแบบสำหรับ ssh URL ใน git อีกจุดหนึ่งคือโดยค่าเริ่มต้นการกำหนดค่าอัปสตรีมของmasterไม่มีผลกระทบต่อพฤติกรรมของgit push เว้นแต่คุณได้push.defaultตั้งค่าเป็นtracking(หรือupstreamในรุ่นที่ใหม่กว่า) - ฉันโพสต์บล็อกเกี่ยวกับแหล่งที่มาของความสับสนนี้: longair.net/blog/2011 /
02/27

1
การแก้ไขเล็กน้อยในความคิดเห็นนั้น - หากไม่มีpush.defaultการกำหนดค่าอัปสตรีมจะใช้เพื่อค้นหารีโมตเริ่มต้นเมื่อคุณใช้git pushแต่จะไม่มีผลต่อการแม็พของการอ้างอิง
Mark Longair

1
ฉันสงสัยว่าทำไม "Inside Out" โดยปกติแล้ว "กล่องดำ" นั้นง่ายมากที่จะเรียนรู้ ... มันเป็นเหมือนวิธีการจากบนลงล่างพร้อมกับด้านบน - อินเทอร์เฟซ - สิ่งที่คุณป้อนและสิ่งที่คุณได้รับ กำหนดไว้อย่างดีและหวังว่าจะง่ายเช่นกัน ผู้ใช้ทุกคนต้องใส่ใจคือ "ส่วนต่อประสาน" และไม่จำเป็นต้องรู้ว่าอะไรอยู่ข้างใน หากผู้ใช้ต้องการทราบข้อมูลเพิ่มเติมวิธีพิเศษในการนำไปใช้จะเป็นการดีที่จะรู้ แต่โดยทั่วไปแล้วจะเป็นตัวเลือก
nonopolarity

3
Apropos บ็อกซ์สีดำกับด้านในออก Git เป็นสิ่งแรกที่ฉันพบว่าจริง ๆ แล้วง่ายต่อการเรียนรู้จากภายในมากกว่าจาก "ส่วนต่อประสาน" ไม่ว่าจะเป็นวิธีที่ถูกต้องหรือไม่เป็นที่ถกเถียงกัน ฉันแค่บอกว่าข้างในมีประสิทธิภาพมากขึ้นเมื่อพูดถึงคอมไพล์
Noufal Ibrahim

9
"คอมไพล์เหมือน UNIX ผู้ใช้เป็นมิตร แต่จู้จี้จุกจิกเกี่ยวกับมันเป็นเพื่อน" มันยอดเยี่ยมมากฉันต้องการพิมพ์บนเสื้อยืด
proflux

41

อัปเดต: โปรดทราบว่าคำตอบที่ยอมรับในปัจจุบันจะทำให้เกิดความเข้าใจผิดทั่วไปเกี่ยวกับพฤติกรรมของgit pushซึ่งไม่ได้รับการแก้ไขแม้จะมีความคิดเห็นที่ชี้ออกมา

ข้อมูลสรุปของคุณเกี่ยวกับรีโมต - เช่นชื่อเล่นสำหรับ URL ของที่เก็บ - ถูกต้อง

เหตุใด URL จึงไม่ git: //git@github.com/peter/first_app.git แต่ในไวยากรณ์อื่น - ไวยากรณ์นั้นคืออะไร ทำไมต้องลงท้ายด้วย. git ฉันพยายามไม่ใช้. git ตอนท้ายและใช้งานได้เช่นกัน ถ้าไม่ใช่. git แล้วจะมีอะไรอีก? ดูเหมือนว่า git ตอนเริ่มต้นจะเป็นบัญชีผู้ใช้บนเซิร์ฟเวอร์ git หรือไม่?

URL สองรายการที่คุณกล่าวถึงระบุว่าควรใช้โปรโตคอลการขนส่งสองแบบที่แตกต่างกัน การเริ่มต้นด้วยgit://สำหรับ git โปรโตคอลซึ่งโดยปกติจะใช้สำหรับการเข้าถึงที่เก็บแบบอ่านอย่างเดียวเท่านั้น คนอื่น ๆgit@github.com:peter/first_app.gitเป็นหนึ่งในวิธีที่แตกต่างกันของการระบุการเข้าถึงพื้นที่เก็บข้อมูลผ่าน SSH - นี่คือ "ไวยากรณ์ SCP-สไตล์" ที่อธิบายไว้ในเอกสาร ชื่อผู้ใช้ในไวยากรณ์สไตล์ของ scp นั้นgitเป็นเพราะวิธีการที่ GitHub จัดการกับการระบุผู้ใช้โดยที่ชื่อผู้ใช้นั้นจะถูกละเว้นและผู้ใช้จะถูกระบุตามคู่คีย์ SSH ที่พวกเขาใช้ในการตรวจสอบสิทธิ์

สำหรับฟุ่มเฟื่อยของคุณได้สังเกตเห็นว่าหลังจากที่การผลักดันครั้งแรกแล้วคุณสามารถเพียงแค่ทำgit push origin master git pushนี่เป็นเพราะชุดค่าเริ่มต้นที่จำได้ยาก แต่มีประโยชน์โดยทั่วไป :)

  • หากไม่ได้ระบุระยะไกลจะใช้การกำหนดค่าระยะไกลสำหรับสาขาปัจจุบัน (ในremote.master.urlกรณีของคุณ) หากยังไม่ได้ตั้งค่าระบบoriginจะใช้งาน
  • ถ้าไม่มี "refspec" (เช่นmaster, master:my-experimentฯลฯ ) ระบุค่าเริ่มต้นแล้วคอมไพล์ที่จะผลักดันทุกสาขาในประเทศที่มีชื่อเดียวกับสาขาในระยะไกลได้ หากคุณเพียงแค่มีสาขาที่เรียกว่าmasterในการร่วมกันระหว่างพื้นที่เก็บข้อมูลและรีโมทหนึ่งเดียวของคุณที่จะเป็นเช่นเดียวกับการผลักดันของคุณจะห่างไกลmastermaster

โดยส่วนตัวเนื่องจากฉันมักจะมีสาขาหัวข้อมากมาย (และมักจะ remotes หลาย) ฉันมักจะใช้แบบฟอร์ม:

git push origin master

... เพื่อหลีกเลี่ยงการกดสาขาอื่นโดยไม่ตั้งใจ


ในการตอบกลับความคิดเห็นของคุณเกี่ยวกับคำตอบอื่นมันฟังดูราวกับว่ากำลังเรียนรู้เกี่ยวกับคอมไพล์จากบนลงล่างอย่างมีประสิทธิภาพมาก - คุณค้นพบว่าค่าเริ่มต้นใช้งานได้และคำถามของคุณถามว่าทำไม;) ถึง จะรุนแรงมากขึ้นคอมไพล์สามารถใช้เป็นหลักเหมือนกับ SVN แต่การรู้จักบิตเกี่ยวกับรีโมตและกิ่งไม้หมายความว่าคุณสามารถใช้มันได้อย่างยืดหยุ่นมากขึ้นและสิ่งนี้สามารถเปลี่ยนวิธีการทำงานของคุณให้ดีขึ้นได้ คำพูดของคุณเกี่ยวกับหลักสูตรภาคการศึกษาทำให้ฉันนึกถึงบางสิ่งที่ Scott Chacon กล่าวในการสัมภาษณ์พอดคาสต์ - นักเรียนได้รับการสอนเกี่ยวกับเครื่องมือพื้นฐานทุกประเภทในวิทยาการคอมพิวเตอร์และวิศวกรรมซอฟต์แวร์ แต่การควบคุมเวอร์ชันแทบจะไม่มาก ระบบควบคุมเวอร์ชันแบบกระจายเช่น git และ Mercurial ตอนนี้มีความสำคัญมากและมีความยืดหยุ่นดังนั้นจึงเป็นหลักสูตรการสอนที่คุ้มค่าสำหรับพวกเขาเพื่อให้ผู้คนมีพื้นฐานที่ดี

มุมมองของฉันคือด้วยgitเส้นโค้งการเรียนรู้นี้มีค่าอย่างยิ่ง - การทำงานกับหัวข้อจำนวนมากรวมเข้าด้วยกันได้อย่างง่ายดายและผลักดันและดึงพวกเขาเกี่ยวกับที่เก็บต่างๆนั้นมีประโยชน์อย่างน่าอัศจรรย์เมื่อคุณมั่นใจในระบบ เป็นเรื่องโชคร้ายที่:

  • เอกสารหลักสำหรับ git นั้นยากที่จะแยกวิเคราะห์สำหรับผู้มาใหม่ (แม้ว่าฉันจะโต้แย้งว่าหากคุณ Google สำหรับคำถามคอมไพล์เกือบทุกคนเนื้อหาการสอนที่มีประโยชน์ (หรือคำตอบซ้อนมากเกินไป :)) จะเกิดขึ้นทุกวัน)
  • มีพฤติกรรมแปลก ๆ บางอย่างในคอมไพล์ที่ยากที่จะเปลี่ยนแปลงในขณะนี้เพราะสคริปต์จำนวนมากอาจพึ่งพาพวกเขา แต่สร้างความสับสนให้กับผู้คน

ฉันคิดว่าหนังสือ pro git เป็นทรัพยากรที่ยอดเยี่ยมและเข้าใจง่ายสำหรับผู้มาใหม่ ทำให้เส้นโค้งการเรียนรู้ราบรื่นขึ้นอย่างมาก นอกจากนี้ฉันคิดว่าการพยายาม "ทำแผนที่" SVN และแนวคิดแบบรวมศูนย์อื่น ๆ ลงบนคอมไพล์จะทำให้ถนนนั้นยากขึ้นแทนที่จะราบรื่นกว่า การรีเซ็ตแบบสมบูรณ์เป็นวิธีที่รวดเร็วและง่ายขึ้นในประสบการณ์ของฉัน
Noufal Ibrahim

@ นูฟาลอิบราฮิม: ฉันเห็นด้วยกับทุกประเด็นของคุณ ฉันไม่ได้พยายามที่จะแนะนำ "การทำแผนที่" แนวคิดของ SVN ไปสู่เรื่องคอมไพล์เนื่องจากฉันรู้ว่าความสับสนที่น่ากลัวนั้นอาจเกิดขึ้นได้ - มีวิธีที่ดีกว่าในการสอนคอมไพล์จากบนลงล่าง
Mark Longair

9

ดูที่ไวยากรณ์สำหรับเพิ่ม repo ระยะไกล

git remote add origin <url_of_remote repository>

ตัวอย่าง:

git remote add origin git@github.com:peter/first_app.git

ให้เราแยกคำสั่ง:

git remoteสิ่งนี้ใช้สำหรับจัดการเซิร์ฟเวอร์ Central ของคุณเพื่อโฮสต์ที่เก็บ git ของคุณ

อาจเป็นเพราะคุณกำลังใช้Githubสำหรับสิ่งที่เก็บส่วนกลาง ฉันจะให้ตัวอย่างและอธิบายคำสั่งgit remote add origin

สมมติว่าฉันทำงานกับGitHubและBitBucketสำหรับเซิร์ฟเวอร์ส่วนกลางสำหรับที่เก็บ git และได้สร้างที่เก็บข้อมูลบนเว็บไซต์ทั้งสองสำหรับโครงการแอปแรกของฉัน

ตอนนี้ถ้าฉันต้องการผลักดันการเปลี่ยนแปลงของฉันไปยังเซิร์ฟเวอร์ git ทั้งสองนี้ฉันจะต้องบอก git วิธีการเข้าถึงที่เก็บส่วนกลางเหล่านี้ ดังนั้นฉันจะต้องเพิ่มสิ่งเหล่านี้

สำหรับ GitHub

git remote add gh_origin https://github.com/user/first-app-git.git

และสำหรับ BitBucket

git remote add bb_origin https://user@bitbucket.org/user/first-app-git.git

ฉันใช้ตัวแปรสองตัว (เพราะมันง่ายสำหรับฉันที่จะเรียกพวกมันว่าตัวแปร) gh_origin (gh สำหรับ GITHUB) และbb_origin (bb สำหรับ BITBUCKET) เพียงเพื่ออธิบายว่าคุณสามารถเรียกสิ่งที่เราต้องการได้

ตอนนี้หลังจากทำการเปลี่ยนแปลงฉันจะต้องส่ง (ดัน) การเปลี่ยนแปลงเหล่านี้ทั้งหมดไปยังที่เก็บส่วนกลางเพื่อให้ผู้ใช้รายอื่นเห็นการเปลี่ยนแปลงเหล่านี้ ดังนั้นฉันจึงโทร

ผลักดันไปที่ GitHub

git push gh_origin master

ผลักไปที่ BitBucket

git push bb_origin master

gh_originมีการถือครองมูลค่าของhttps://github.com/user/first-app-git.gitและbb_originมีมูลค่าการถือhttps: //user@bitbucket.org/user/first-app-git.git

ตัวแปรสองตัวนี้ทำให้ชีวิตของฉันง่ายขึ้น

เมื่อใดก็ตามที่ฉันต้องการส่งการเปลี่ยนแปลงรหัสของฉันฉันจำเป็นต้องใช้คำนี้แทนการจดจำหรือพิมพ์ URL สำหรับสิ่งเดียวกัน

เวลาส่วนใหญ่ที่คุณไม่เห็นอะไรเลยนอกจากจุดกำเนิดเป็นส่วนใหญ่ที่คุณจะจัดการกับที่เก็บส่วนกลางเดียวเท่านั้นเช่น Github หรือ BitBucket


5
  1. .gitที่ท้ายชื่อพื้นที่เก็บข้อมูลเป็นเพียงการประชุม project.gitโดยปกติบนเซิร์ฟเวอร์ที่เก็บคอมไพล์จะถูกเก็บไว้ในไดเรกทอรีที่มีชื่อ ลูกค้า git และโปรโตคอลให้เกียรติอนุสัญญานี้โดยการทดสอบproject.gitเมื่อprojectมีการระบุเฉพาะ

  2. git://git@github.com/peter/first_app.gitไม่ใช่ git url ที่ถูกต้อง เก็บ Git สามารถระบุและเข้าถึงได้ผ่านทางรูปแบบ URL ต่างๆที่ระบุไว้ที่นี่ git@github.com:peter/first_app.git เป็นsshURL ที่กล่าวถึงในหน้านั้น

  3. gitมีความยืดหยุ่น จะช่วยให้คุณติดตามสาขาในพื้นที่ของคุณกับสาขาใด ๆ ของพื้นที่เก็บข้อมูลใด ๆ ในขณะที่masterการติดตามorigin/master( สาขาเริ่มต้นในท้องถิ่นของคุณ) (สาขาเริ่มต้นระยะไกล) เป็นสถานการณ์ที่ได้รับความนิยม แต่ไม่ใช่สากล หลายครั้งที่คุณอาจไม่ต้องการทำเช่นนั้น นี่คือเหตุผลที่แรกgit pushคือ verbose มันบอกคอมไพล์จะทำอะไรกับท้องถิ่นmasterสาขาเมื่อคุณทำหรือgit pullgit push

  4. ค่าเริ่มต้นสำหรับgit pushและgit pullคือทำงานกับรีโมตของสาขาปัจจุบัน นี่เป็นค่าเริ่มต้นที่ดีกว่าต้นแบบดั้งเดิม ผลักดันวิธีคอมไพล์กำหนดนี้จะมีการอธิบายที่นี่

git ค่อนข้างสง่างามและเข้าใจได้ง่าย แต่มีช่วงการเรียนรู้ที่จะเดินผ่าน


1
ตามที่ฉันแสดงความคิดเห็นในคำตอบอื่น ๆ ในการกำหนดค่าเริ่มต้นของ git git pushไม่ได้ใช้ตัวแปรการตั้งค่าที่มีการตั้งค่าgit branch/checkout --trackเพื่อกำหนดอ้างอิงระยะไกลที่จะผลักดัน คุณพูดถูกว่า git pull นั้นใช้สิ่งเหล่านี้
Mark Longair

0

Git แหล่งกำเนิดเพิ่มระยะไกล:

มันรวมศูนย์ซอร์สโค้ดของคุณไปยังโปรเจ็กต์อื่น ๆ มันถูกพัฒนาบนพื้นฐานของ Linux, โอเพ่นซอร์สที่สมบูรณ์และทำให้โค้ดของคุณมีประโยชน์ต่อผู้ใช้ git อื่น ๆ เราเรียกมันว่าเป็นข้อมูลอ้างอิง

พุชโค้ดของคุณไปยังที่เก็บ git โดยใช้ URL ระยะไกลของฮับ git

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