จะคัดลอกคอมมิตจากที่เก็บ Git หนึ่งไปยังอีกที่หนึ่งได้อย่างไร


107

เมื่อสัปดาห์ที่แล้วฉันสร้าง Github repo และลืมเลือกใบอนุญาตสำหรับ repo ตอนนี้มีการคอมมิชชันขนาดใหญ่แล้ว 3 รายการ

ฉันถามผู้ร่วมให้ข้อมูลทั้ง 3 คนว่าใช้ได้หรือไม่ถ้าฉันลบ repo แล้วสร้างอีกครั้งโดยใช้ชื่อเดียวกันและคราวนี้เลือกใบอนุญาตเมื่อสร้าง repo และพวกเขาก็ทำได้ดี

คำถาม

มีวิธีใดบ้างที่ฉันนำคอมมิตไปสู่ ​​repo ใหม่ (ครั้งนี้คอมมิตแรกคือไฟล์ LICENSE) และยังคงเก็บข้อมูลเมตาการคอมมิตไว้หรือไม่


1
คุณยังสามารถเพิ่มใบอนุญาตให้กับ repo เดิมได้ ดูhelp.github.com/articles/open-source-licensing/…สำหรับรายละเอียด
edwinksl

การทำสำเนาคอมไพล์ที่เป็น
Marc K

คำตอบ:


186

มีวิธีใดบ้างที่ฉันนำคอมมิตไปสู่ ​​repo ใหม่ (ครั้งนี้คอมมิตแรกคือไฟล์ LICENSE) และยังคงเก็บข้อมูลเมตาการคอมมิตไว้หรือไม่

ใช่โดยการเพิ่มรีโมทและการเลือกเชอร์รี่ที่คอมมิตไว้ด้านบนของคอมมิตแรกของคุณ

# add the old repo as a remote repository 
git remote add oldrepo https://github.com/path/to/oldrepo

# get the old repo commits
git remote update

# examine the whole tree
git log --all --oneline --graph --decorate

# copy (cherry-pick) the commits from the old repo into your new local one
git cherry-pick sha-of-commit-one
git cherry-pick sha-of-commit-two
git cherry-pick sha-of-commit-three

# check your local repo is correct
git log

# send your new tree (repo state) to github
git push origin master

# remove the now-unneeded reference to oldrepo
git remote remove oldrepo

คำตอบที่เหลือคือหากคุณยังต้องการเพิ่ม LICENSE ให้กับ repo ก่อนหน้าของคุณ

ใช่. คุณสามารถวางคอมมิต LICENSE เป็นคอมมิตแรกได้

Rebasing เป็นวิธีการจัดเรียงคำสั่งคอมมิตใหม่ในขณะที่รักษาผู้เขียนคอมมิตและวันที่คอมมิตไว้ทั้งหมด

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

นี่คือวิธีที่คุณได้รับ LICENSE คอมมิตเป็นครั้งแรก

1. อัปเดตและสร้างฐานข้อมูลสำเนาในเครื่องของคุณใหม่

ตรวจสอบโครงการของคุณและวางไฟล์ LICENSE ในคอมมิตที่ด้านบนของ 3 คอมมิตสแต็กปัจจุบันของคุณ

#create LICENSE file, edit, add content, save
git add LICENSE
git commit -m 'Initial commit'

จากนั้นทำการ rebase แบบโต้ตอบบนสาขาหลักเพื่อจัดเรียงคอมมิตใหม่

git rebase -i --root

มันจะเปิดตัวแก้ไข ย้ายบรรทัดล่างสุด (คอมมิต "Initial คอมมิต" ซึ่งเป็นคอมมิตล่าสุด) ไปที่ด้านบนสุดของไฟล์ จากนั้นบันทึกและออกจากโปรแกรมแก้ไข

ทันทีที่คุณออกจากโปรแกรมแก้ไขคอมไพล์จะเขียนคอมมิตตามลำดับที่คุณระบุ

ตอนนี้คุณได้อัปเดตสำเนาที่เก็บในเครื่องแล้ว ทำ:

git log

เพื่อตรวจสอบ

2. บังคับให้ผลักดันสถานะ repo ใหม่ของคุณไปที่ github

เมื่ออัปเดตสำเนาของคุณแล้วคุณต้องบังคับให้ส่งไปที่ github

git push -f origin master

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

3. ประสานผู้ทำงานร่วมกันกับ github

สุดท้ายนี้ผู้ทำงานร่วมกันทั้งหมดจะต้องซิงโครไนซ์กับที่เก็บนี้

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

# make sure there are no unsaved changes
git status 

# pull the latest version from github
git fetch  

# move their master branch pointer to the one you published to github.
git reset --hard origin/master

แค่นั้นแหละ. ตอนนี้ทุกคนควรจะซิงค์กันแล้ว


2
ตอบโจทย์มาก! ขอบคุณ!
Kyrol

ประหยัดเวลาได้มาก ขอบคุณ!
an0nh4x0r

9

ฉันมีปัญหาคล้ายกันที่ฉันลืมแยก repo ไปยัง github ของฉันและเพิ่มการกระทำหลายอย่างก่อนที่ฉันจะตระหนักถึงความผิดพลาดของฉัน

ฉันพบวิธีง่ายๆ

ก่อนอื่นให้ถอดรีโมทไปที่ repo เดิม

git remote remove origin

ประการที่สองเพิ่มรีโมทไปยังทางแยกใหม่บน GitHub ของฉัน

git remote add origin <my repo URL>

จากนั้นฉันก็ดันไปที่ต้นกำเนิดและการกระทำทั้งหมดของฉันปรากฏบน GitHub ของฉัน


1
เพื่อเพิ่มสิ่งนี้เมื่อฉันผลักดันฉันต้องทำgit push --set-upstream origin masterแต่ Git ทำให้คุณรู้เรื่องนี้
MRichards

ทางออกที่ดีและง่าย!
mecograph

3
  • Git ปลายทาง = UrlD (เนื้อหาที่มีอยู่ไม่สำคัญ)
  • SourceGit = UrlS

    git clone UrlS
    
    git remote add origin2 UrlD
    
    git push -f origin2 master
    

ตอนนี้ Destination จะมีข้อมูลเดียวกันกับ Source (คุณยังสามารถใช้ origin แทน origin2 ได้)


1

ตามคำตอบของ @ Moocowmoo แต่พยายามปรับปรุงให้ดีขึ้นอีกเล็กน้อย

สิ่งที่แตกต่างออกไปคือพยายามหลีกเลี่ยงความขัดแย้งให้มากที่สุดเพียงแค่สมมติว่ารีโมตถูกต้อง

อย่างไรก็ตามมันไม่สามารถจัดการไฟล์ที่ถูกลบได้ดีดังนั้นจึงยังมีองค์ประกอบที่ต้องใช้

# assuming you are already on the branch you want to be
git remote add oldrepo https://github.com/path/to/oldrepo
git fetch oldrepo

# take all or subset of changes from a branch
git cherry-pick --strategy recursive --strategy-option theirs oldestCommitHash^..latestCommitHash

# or take all changes included in a specific merge commit (easiest)
git cherry-pick --strategy recursive --strategy-option theirs mergeCommitHash^..mergeCommitHash

# handling deleted files/unhandled conflicts
# just keep repeating this section
git mergetool
# either c/m or d based on if you want to keep or delete the files
git cherry-pick --continue

0

ฉันใช้แนวทางต่อไปนี้:

  • โคลน repo ต้นทางไปยังโฟลเดอร์เช่น / c / SrcRepo

  • โคลน repo ปลายทางไปยังโฟลเดอร์เช่น / c / DstRepo และเปลี่ยนไปยังสาขาปลายทาง

  • ในโฟลเดอร์รากของ repo ปลายทางให้รันคำสั่ง:

    git pull / c / SrcRepo srcBranch - อนุญาตให้ไม่เกี่ยวข้อง - ประวัติ

ไม่จำเป็นต้องสร้างการอ้างอิงระยะไกลเพิ่มเติม

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