Git pull — 3 แบบ

Apirak

--

ผมเจอ hint ของ Git บ่อยๆ แล้วก็ไม่แน่ใจว่าต้องเลือกแบบไหน ปกติก็จะเลือก merge ไว้ก่อน เพราะคุ้นเคย แต่วันนี้สงสัยเลยไปลองค้นดู

❯ git pull

hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint: git config pull.rebase false # merge
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.

ด้านบนเป็น hint ที่ทาง git บอกเราตอนสั่ง git pull แล้วมันตัดสินใจไม่ได้ว่าจะใช้ท่าไหนในการ pull ดี มันเลยมาถามเราไว้ก่อน เราลองมาดูกันว่า 3 แบบต่างกันอย่างไร

สมติก่อนว่าเรามี Branch แบบนี้

local:   A---B---C (เราพัฒนา C แล้วต้องการ pull D ลงมา)

server: A---B---D (เพื่อนร่วมงานพัฒนา D แล้ว push ขึ้น server)

1. สั่ง git config pull.rebase false — Merge

อันนี้ท่าปกติเลย ก็มองเหมือนว่าเป็น 2 branch แล้วเอามาเชื่อมกัน ก็จะทำให้เห็นแผลเป็นจากการเชื่อมต่อ

A---B---C---E (E คือ merge commit ที่มีทั้ง C และ D ใหม่)
\ /
D---

ซึ่งก็ดีเพราะทำให้เราเข้าใจว่าเกิดอะไรขึ้น แต่ก็จะทำให้เส้นสวยๆ เป็นแผล ยิ่งมีคนเยอะๆ เส้นจะยิ่งมั่วเลย สุดท้ายกลายเป็นตรวจสอบอะไรไม่ได้อยู่ดี

2. สั่ง git config pull.rebase true — Rebase

อันนี้คือให้เอาของเราไปต่อท้ายเลย ทำให้ไม่เห็นแผลเป็นใดๆ เส้นราบเรียบสวยงาม

A---B---D---C (C คือการเปลี่ยนแปลงที่นำมาต่อหลัง D)

ข้อดีคือมันเรียบร้อย ข้อเสียคือมันจะมั่วๆ ได้ ยิ่งถ้าเราทำอะไรแปลกๆ เช่น push เข้า remote ไปก่อนแล้ว ค่อย pull ลงมา

3. สั่ง git config pull.ff only — fast-forward only

ถ้าเป็นอันนี้มันจะพยายามเอา C ไปต่อที่หัวให้ได้ ดังนั้นถ้าที่ Server มีการพัฒนา D อยู่แล้วมันจะไม่ยอมทำ แล้วให้เราเลือกระหว่างข้อ 1 กับ 2 อีกที ตัวอย่างที่ทำได้ของข้อ 3 คือแบบนี้ครับ

สมติว่าเรามี code แบบนี้

local:   A---B (ไม่มีการเปลี่ยนแปลงใหม่)
remote: A---B---C (มีการเพิ่ม commit C)

ถ้าใช้ fast-forward จะได้แบบนี้

A---B---C (โลคอลเลื่อนไปที่ C โดยไม่ต้อง merge)

ข้อดีสำหรับแบบนี้คือปลอดภัยแน่นอน ยิ่งตั้ง default เป็นแบบนี้ก็จะทำให้มันทำแบบตรงไปตรงมาเท่านั้น ถ้ามันทำไม่ได้ค่อยมาถามอีกที แต่ก็เสียเวลาครับ ถ้าปกติเราก็เลือก Rebase การตั้งให้ default เป็น Rebase ไปเลยก็จะง่าย

ตั้ง Default อย่างไร

ถ้าต้องการให้ rebase เป็น default จะต้องสั่งแบบนี้

git config --global pull.rebase true

หรือถ้าจะสั่งเป็นครั้งๆ ก็ให้สั่งแบบนี้ครับ

git pull --rebase
git pull --no-rebase
git pull --ff-only

ผมชอบแบบ rebase เพราะมันดูเรียบร้อยดี ^^ ทำให้ตอนที่มันแปลกมันเห็นได้ชัดๆ ไม่ไปปนกับแผลเป็นเล็กๆ น้อยอื่นๆ

--

--

No responses yet