คำถามติดแท็ก branching

การแยกในการควบคุมการแก้ไขคือการทำซ้ำของวัตถุภายใต้การควบคุมการแก้ไขเพื่อให้การแก้ไขสามารถเกิดขึ้นในแบบคู่ขนานไปตามกิ่งไม้ทั้งสอง

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

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

2
Git branching และการติดแท็กแนวทางปฏิบัติที่ดีที่สุด
ฉันกำลังเรียนรู้ที่จะใช้ Git โดยการอ่านPro Git ตอนนี้ฉันกำลังเรียนรู้เกี่ยวกับการแตกแขนงและแท็ก คำถามของฉันคือเมื่อฉันควรใช้สาขาและเมื่อฉันควรใช้แท็ก? ตัวอย่างเช่นสมมติว่าฉันสร้างสาขาสำหรับเวอร์ชัน 1.1 ของโครงการ เมื่อฉันเสร็จสิ้นและปล่อยรุ่นนี้ฉันควรออกจากสาขาเพื่อทำเครื่องหมายรุ่นที่วางจำหน่ายหรือไม่ หรือฉันควรเพิ่มแท็ก หากฉันเพิ่มแท็กฉันควรลบสาขาเวอร์ชัน (สมมติว่ามันรวมเข้ากับมาสเตอร์หรือสาขาอื่น ๆ )

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

5
อะไรคือข้อดีของการใช้การแยกเป็นนักพัฒนาเดี่ยว?
ก่อนอื่นฉันตระหนักว่ามีคำถามมากมายที่ถูกถามเกี่ยวกับ VCS ในฐานะนักพัฒนาเดี่ยว แต่พวกเขามักจะกว้างเกินไป ปัญหานี้เกี่ยวข้องกับการแตกแขนงเพียงอย่างเดียวและยังคงถูกทำเครื่องหมายว่าซ้ำกัน ... ความซ้ำซ้อนที่ควรจะทำซ้ำอีกครั้งนั้นเป็นอีกคำถามหนึ่งที่กว้างเกินไปและไม่เกี่ยวข้องกับการแยกย่อยโดยเฉพาะ นั่นเป็นวิธีที่คำถามของฉันไม่เหมือนใคร อะไรคือข้อดีของการใช้การแยกทางในฐานะนักพัฒนาเดี่ยว? ฉันมักจะเห็นว่ามันแนะนำแม้ในบริบทเดี่ยว -dev แต่เท่าที่ฉันสามารถมองเห็นนอกเหนือจากการใช้ลำตัว 'ต้นแบบ' เพื่อการพัฒนาและการแตกแขนงออกไปทำงานรหัสพร้อมออกฉันไม่เห็นว่า ฉันสามารถควบคุมพลังของการแยก (ตัวอย่างเช่นเพื่อแยกคุณสมบัติใหม่) โดยไม่ทำให้กระบวนการพัฒนาทั้งหมดซับซ้อนเกินไป

13
ไปที่สาขาหรือไม่ที่จะแตกสาขา?
เมื่อไม่นานมานี้เวิร์กโฟลว์การพัฒนาของฉันมีดังต่อไปนี้: รับคุณสมบัติจากเจ้าของผลิตภัณฑ์ ทำสาขา (หากคุณลักษณะมากกว่า 1 วัน) นำไปใช้ในสาขา ผสานการเปลี่ยนแปลงจากสาขาหลักไปยังสาขาของฉัน (เพื่อลดความขัดแย้งระหว่างการรวมย้อนหลัง) ผสานสาขาของฉันกลับไปที่สาขาหลัก บางครั้งมีปัญหาในการรวม แต่โดยทั่วไปฉันชอบมัน แต่เมื่อเร็ว ๆ นี้ฉันเห็นผู้ติดตามความคิดมากขึ้นเรื่อย ๆ ที่จะไม่สร้างสาขาเพราะมันยากที่จะฝึกการรวมกลุ่มอย่างต่อเนื่องการจัดส่งต่อเนื่อง ฯลฯ และฟังดูตลกโดยเฉพาะจากผู้ที่มีพื้นหลัง VCS กระจาย Git, Mercurial ฯลฯ ดังนั้นคำถามคือเราควรใช้สาขาทุกวันนี้ไหม?

8
เป็นวิธีปฏิบัติที่ดีหรือไม่ที่จะใช้กิ่งไม้ในการบำรุงรักษาซอฟต์แวร์รุ่นต่าง ๆ กัน?
เรามีผลิตภัณฑ์ที่มีรุ่นที่แตกต่างกันเล็กน้อย ความแตกต่างอยู่เล็กน้อย: สตริงที่แตกต่างกันตรงนี้และที่นั่น, ตรรกะเพิ่มเติมเล็กน้อยในหนึ่ง, ความแตกต่างของตรรกะในอีกเล็กน้อย เมื่อมีการพัฒนาซอฟต์แวร์การเปลี่ยนแปลงส่วนใหญ่จำเป็นต้องเพิ่มในแต่ละรุ่น อย่างไรก็ตามมีบางอย่างที่ทำไม่ได้และมีบางอย่างที่ต้องแตกต่างกัน มันเป็นการใช้สาขาที่ถูกต้องหรือไม่ถ้าฉันมี release-editionA และ release-editionB (..etc) มี gotchas บ้างไหม? แนวทางปฏิบัติที่ดี? อัปเดต: ขอบคุณสำหรับความเข้าใจทุกคนคำตอบที่ดีมากมายที่นี่ ฉันทามติทั่วไปน่าจะเป็นความคิดที่ดีที่จะใช้สาขาเพื่อจุดประสงค์นี้ สำหรับทุกคนที่สงสัยวิธีแก้ปัญหาสุดท้ายของฉันคือการทำให้สตริงเป็นภายนอกและตั้งค่าตรรกะที่แตกต่างกันเป็นปลั๊กอินหรือสคริปต์
72 git  branching 

7
ทำงานในสาขาที่ต้องพึ่งพาสาขาอื่นที่กำลังตรวจสอบอยู่
git ช่วยจัดการกับสถานการณ์ด้านล่างได้อย่างไร: ฉันมีภาระงานแบ่งออกเป็น 2 ส่วนคือส่วนแบ็กเอนด์และส่วนหน้า ฉันสร้างคำขอดึงเพื่อรวมการเปลี่ยนแปลงแบ็กเอนด์และรอให้รวมเข้าด้วยกัน ในขณะที่รอฉันไม่สามารถทำงานกับการเปลี่ยนแปลงส่วนหน้าได้เพราะมันขึ้นอยู่กับการเปลี่ยนแปลงแบ็กเอนด์และสิ่งเหล่านั้นยังไม่สามารถใช้ได้ในสาขาหลัก วิธีที่ดีที่สุดในการดึงการเปลี่ยนแปลงไปยังสาขาการเปลี่ยนแปลงส่วนหน้าจากสาขาการเปลี่ยนแปลงแบ็กเอนด์ในขณะที่มันยังอยู่ในระหว่างการตรวจสอบ?
65 git  branching 

7
คุณจัดการกับการรวมรหัสจากหลาย ๆ สาขา / นักพัฒนาแต่ละ sprint ได้อย่างไร
เพิ่งได้รับการโทรย้อนยุคที่นักพัฒนาแสดงความกังวลเกี่ยวกับการบูรณาการเรื่องราวของพวกเขาในสาขาหลักแต่ละการวิ่ง นักพัฒนารหัสทั้งหมดภายในสาขาของตัวเองและในตอนท้ายของการวิ่งพวกเขาทั้งหมดรวมเป็นหนึ่งสาขาหลัก จากนั้นผู้พัฒนารายหนึ่ง (โดยปกติจะเป็นคนเดียวกัน) จะเหลือหน้าที่ในการทำให้แน่ใจว่าทุกอย่างได้รวมเข้ากับโค้ดของ dev อื่น ๆ (การเปลี่ยนแปลงส่วนใหญ่อยู่ในหน้าเดียวกันตัวอย่างเช่นเรื่องการแสดงข้อมูลเรื่องราวการกรองข้อมูลและ ตัวบ่งชี้ SLA) เราจะลดภาระนี้และทำให้รหัสของเรารวมเข้าด้วยกันได้ง่ายขึ้นได้อย่างไร จากมุมมองของฉันการมี PO หรือ SM จัดลำดับความสำคัญของเรื่องราวด้วยวิธีที่มีประสิทธิภาพมากขึ้นดังนั้นเราจึงไม่มีการพึ่งพาเหล่านี้ในการวิ่งเดียวกันอาจช่วยแก้ปัญหาบางอย่างได้ คนอื่นจะรับมือกับเรื่องนี้อย่างไร หรือนี่เป็นเพียงส่วนหนึ่งของกระบวนการ?

11
เคยตกลงใช้รหัสไม่ทำงานหรือไม่?
เป็นความคิดที่ดีหรือไม่ที่ต้องส่งรหัสการทำงานเท่านั้น? การมอบหมายนี้ไม่จำเป็นต้องออกจากที่เก็บในสถานะใช้งานเป็น: ... เราอยู่ในช่วงเริ่มต้นของการออกแบบรหัสยังไม่เสถียร ... คุณเป็นผู้พัฒนาเพียงผู้เดียวในโครงการ คุณรู้ว่าทำไมสิ่งต่าง ๆ ไม่ทำงาน นอกจากนี้คุณไม่ได้หยุดการทำงานของใครก็ตามโดยการส่งรหัสที่ผิดพลาด ... รหัสในปัจจุบันใช้งานไม่ได้ เราจะทำการเปลี่ยนแปลงครั้งใหญ่ ลองทำเพื่อที่จะมีประเด็นที่จะย้อนกลับไปสู่สิ่งที่น่าเกลียด ... สายโซ่ยาวไม่มีปัญหาหากมีรหัสที่ใช้ไม่ได้ในสาขาท้องถิ่น กล่าวคือ ไฟล์ท้องถิ่น การจัดเตรียมพื้นที่ มุ่งมั่นในสาขาท้องถิ่น กระทำในสาขาคุณสมบัติส่วนบุคคลระยะไกล ผสานกับdevelopสาขาระยะไกล ผสานกับmasterสาขาระยะไกล ผสานกับreleaseสาขาระยะไกล ... กระทำก่อนกำหนดกระทำบ่อย ๆ ดังนั้นในคำถามที่เชื่อมโยงข้างต้นคำตอบส่วนใหญ่บอกว่าการคอมไพล์โค้ดที่ไม่สามารถคอมไพล์ได้นั้นไม่มีปัญหาในสาขาท้องถิ่นและฟีเจอร์ ทำไม? มูลค่าของการกระทำที่เสียหายคืออะไร? ที่เพิ่มเข้ามา: มีความคิดเห็นที่ได้รับการโหวตสูงสองสามรายการโดยบอกว่าในสาขาท้องถิ่นสามารถทำได้ทุกอย่างที่ต้องการ อย่างไรก็ตามฉันไม่สนใจด้านเทคนิคของคำถาม แต่ฉันต้องการเรียนรู้แนวปฏิบัติที่ดีที่สุด - นิสัยที่คนที่ทำงานมาหลายปีในอุตสาหกรรมมีผลงานมากที่สุด ฉันประหลาดใจกับคำตอบที่ยอดเยี่ยมมากมาย! พวกเขานำฉันไปสู่ข้อสรุปว่าฉันไม่ชำนาญในการใช้สาขาเพื่อจัดระเบียบโค้ดของฉัน

5
เป็นการดีกว่าที่จะรวม“ บ่อยครั้ง” หรือหลังจากรวมฟีเจอร์สาขาใหญ่แล้วเสร็จ?
พูดได้หลายสาขาจะได้รับการพัฒนาAและBเช่นเดียวกับที่เพิ่มขึ้น "แก้ไขข้อผิดพลาด" Cสาขา ตอนนี้C"เสร็จสิ้น" และถูกรวมเข้ากับต้นแบบแล้ว AและBยังอยู่ในระหว่างการพัฒนาและจะไม่ได้รับการแก้ไขก่อน (อาจ) สาขาการแก้ไขข้อบกพร่องอื่นถูกรวมเข้ากับข้อมูลหลัก มันเป็นความคิดที่ดีที่จะรวมCโดยเร็วที่สุดในฟีเจอร์ใหม่หรือไม่? เพื่อให้คุณสมบัติใหม่อยู่ใกล้เคียงกับที่masterเป็นไปได้? หรือมันจะดีกว่าที่จะปล่อยให้คุณสมบัติใหม่ถูกพัฒนาขึ้นใน "โลก" ของพวกเขาเท่านั้นที่จะรวมเข้ากับต้นแบบเมื่อเสร็จสิ้นแล้ว? จะมีความขัดแย้ง แต่อย่างใดดังนั้นจึงจำเป็นต้องใช้เวลาในการแก้ไขสิ่งเหล่านั้น

3
การนำสาขาที่ผสานมาใช้ซ้ำการปฏิบัติที่ดี?
ปัจจุบันฉันเคยสร้างสาขาใหม่ทุกครั้งที่ฉันต้องเพิ่มฟีเจอร์ใหม่ให้กับแอปพลิเคชันของฉัน เมื่อคุณสมบัติของฉันเสร็จสิ้นและใช้งานได้ฉันจะรวมเข้ากับสาขาหลัก แต่ต่อมาเมื่อฉันต้องการอัปเดตฟีเจอร์นี้ (เช่นการปรับปรุง) มันจะดีกว่าถ้าจะสร้างสาขาใหม่หรือฉันต้องรีบูทก่อนหน้านี้กับมาสเตอร์การอัพเดตจะรวมกันอีกครั้งหรือไม่ ตัวอย่างเช่นฉันมีสาขาที่เรียกว่า modeling-member ในแอปพลิเคชัน Ruby on Rails ต่อมาฉันต้องเพิ่มคุณสมบัติบางอย่างในโมเดลสมาชิก (ซึ่งสร้างในสาขานี้) ฉันควรทำอย่างไร? รีบูทสาขานี้ด้วยมาสเตอร์อัปเดตโมเดลและรวมมันอีกครั้งหรือเพียงแค่สร้างสาขาใหม่
36 git  branching 

12
DVCSes ไม่สนับสนุนการรวมอย่างต่อเนื่องหรือไม่?
บอกว่ามีทีมนักพัฒนาสิบคนที่คล่องแคล่ว ทุกวันพวกเขาแต่ละคนเลือกงานจากคณะกรรมการดำเนินการเปลี่ยนแปลงหลายอย่างจนกระทั่งพวกเขาเสร็จสิ้นภารกิจ (ภายในสิ้นวัน) นักพัฒนาทั้งหมดเช็คอินกับ trunk โดยตรง (สไตล์ Google ทุกการคอมมิทเป็นตัวเลือกรีลีสโดยใช้ฟีเจอร์สลับ ฯลฯ ) หากพวกเขาใช้ CVS ส่วนกลางเช่น SVN ทุกครั้งที่พวกเขาคอมไพล์เซิร์ฟเวอร์บิลด์จะรวมและทดสอบการเปลี่ยนแปลงกับงานของนักพัฒนาอีกเก้าคน บิลด์เซิร์ฟเวอร์จะทำงานค่อนข้างต่อเนื่องตลอดทั้งวัน แต่ถ้าพวกเขาใช้ DCVS เหมือนคอมไพล์ผู้พัฒนาอาจรอจนกว่าพวกเขาจะทำงานให้เสร็จก่อนที่จะผลักดันคอมมิชชันท้องถิ่นของพวกเขาทั้งหมดไปยังที่เก็บส่วนกลาง การเปลี่ยนแปลงของพวกเขาจะไม่ถูกรวมเข้าด้วยกันจนกระทั่งสิ้นสุดวัน ในสถานการณ์สมมตินี้ทีม SVN จะรวมกันอย่างต่อเนื่องบ่อยขึ้นและค้นพบปัญหาการรวมเร็วกว่าทีม git นี่หมายความว่า DVCS นั้นไม่เหมาะสำหรับทีมต่อเนื่องมากกว่าเครื่องมือรวมศูนย์แบบเก่าหรือไม่ พวกคุณรู้ปัญหานี้ได้อย่างไร

5
ฉันเป็นผู้ใช้คอมไพล์สับสนโดยการแตกแขนงของ Mercurial ฉันจะติดตามการเปลี่ยนแปลงเล็กน้อยได้อย่างไร
ฉันเคยใช้คอมไพล์มาก่อน แต่ฉันต้องการมีส่วนร่วมกับไพ ธ อนดังนั้นตอนนี้ฉันต้องเรียนรู้ Mercurial และฉันพบว่ามันน่าหงุดหงิดมาก ดังนั้นฉันจึงทำแผ่นแปะเล็ก ๆ สองสามชิ้นและฉันต้องการติดตามพวกเขาในคอมมิชชัน Mercurial Repository เห็นได้ชัดว่ามี4 วิธีที่จะจัดการกับการแตกแขนงในปรอท 1 และ 4 ดูไร้สาระอย่างสมบูรณ์สำหรับฉันสาขาชื่อดูเหมือนจะมีน้ำหนักมากและฉันรู้สึกว่าฉันไม่ควรใช้พวกเขาสำหรับการแก้ไข 1 คอมมิชชันที่รวดเร็วดังนั้นฉันจึงใช้บุ๊กมาร์ก ตอนนี้แพทช์ของฉันถูกปฏิเสธและฉันต้องการลบสาขาบุ๊กมาร์กของฉันจากที่เก็บของฉัน ตกลงใน git ฉันจะบังคับลบสาขาของฉันและลืมมันดังนั้นฉันลบบุ๊คมาร์คของฉันและตอนนี้ฉันมีปัญหาต่อไปนี้: TortoiseHG และhg logยังคงแสดงให้เห็นว่าการกระทำและdefaultสาขามี 2 หัว และถ้าฉันเข้าใจถูกต้องคุณจะไม่สามารถลบการคอมมิทเป็น hg หากไม่มีปลั๊กอินเพิ่มเติม Mercurial ไม่เพียง แต่แฮช แต่ยังปรับปรุงหมายเลข ในขณะที่ฉันเพิ่มความมุ่งมั่นของตัวเองสองสามข้อความมุ่งมั่นทั้งหมดที่ดึงมาหลังจากนั้นมีหมายเลขการแก้ไขที่แตกต่างจาก repo ส่วนกลางหลัก ฉันhg updateดึงหลังจากย้ายmasterบุ๊กมาร์กของฉันไปยังการคอมมิชชันล่าสุดโดยอัตโนมัติ แต่ฉันไม่สามารถหาวิธีที่จะทำได้ใน TortoiseHG ผมทำอะไรผิดหรือเปล่า? นี่เป็นเรื่องปกติและคาดหวังและฉันควรจะเพิกเฉยต่อปัญหาเหล่านี้หรือไม่ หรือฉันจะทำงานกับสาขาของฉันได้อย่างไร

2
เมื่อใช้ Git จะใช้สาขาหลักสำหรับการพัฒนาที่แนะนำหรือไม่?
อย่างแรกพื้นหลังบางอย่างเราอยู่ในกระบวนการเคลื่อนย้ายทีมโครงการทั้งหมดของเราไปใช้ git และอยู่ในขั้นตอนการวางแนวทางสำหรับวิธีการจัดเก็บที่เก็บเพื่อให้สาขาบางแห่งสามารถตรวจสอบการรวมกลุ่มอย่างต่อเนื่องและ การปรับใช้อัตโนมัติไปยังเซิร์ฟเวอร์ทดสอบ ขณะนี้มีสองรุ่นที่กำลังพัฒนา: ได้รับอิทธิพลอย่างมากจากบทความ nvie.com เกี่ยวกับการประสบความสำเร็จในการแยกย่อยด้วยสาขาหลักซึ่งเป็นรหัสที่เสถียรที่สุด, สาขาการพัฒนาสำหรับโค้ด edge bleeding และสาขาการรวมสำหรับโค้ดที่พร้อมสำหรับการทดสอบ QA โมเดลสำรองที่สาขาหลักเป็นตัวแทนของรหัสการพัฒนา edge edge, Branch Integration สำหรับรหัสที่พร้อมสำหรับการทดสอบ QA และสาขาการผลิตสำหรับรหัสที่เสถียรที่พร้อมสำหรับการปรับใช้ ณ จุดนี้มันเป็นส่วนหนึ่งของความหมายเกี่ยวกับสิ่งที่สาขาหลักหมายถึง แต่กำลังทำการพัฒนาที่แข็งขันในสาขาหลักจริง ๆ แล้วเป็นการปฏิบัติที่ดีหรือไม่จริงหรือไม่เกี่ยวข้องกัน?
32 git  branching 

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