คำตอบนี้ให้คำสั่งที่น่าสนใจตามgit amและนำเสนอโดยใช้ตัวอย่างทีละขั้นตอน
วัตถุประสงค์
- คุณต้องการย้ายไฟล์บางไฟล์หรือทั้งหมดจากที่เก็บหนึ่งไปยังอีกที่หนึ่ง
- คุณต้องการเก็บประวัติของพวกเขา
- แต่คุณไม่สนใจที่จะเก็บแท็กและกิ่งก้าน
- คุณยอมรับประวัติที่ จำกัด สำหรับไฟล์ที่ถูกเปลี่ยนชื่อ (และไฟล์ในไดเรกทอรีที่ถูกเปลี่ยนชื่อ)
ขั้นตอน
- แยกประวัติในรูปแบบอีเมลโดยใช้
 git log --pretty=email -p --reverse --full-index --binary
- จัดโครงสร้างไฟล์ต้นไม้ใหม่และอัปเดตการเปลี่ยนแปลงชื่อไฟล์ในประวัติ [ตัวเลือก]
- ใช้ประวัติใหม่โดยใช้ git am
1. แยกประวัติในรูปแบบอีเมล
ตัวอย่าง: สารสกัดจากประวัติศาสตร์file3, file4และfile5
my_repo
├── dirA
│   ├── file1
│   └── file2
├── dirB            ^
│   ├── subdir      | To be moved
│   │   ├── file3   | with history
│   │   └── file4   | 
│   └── file5       v
└── dirC
    ├── file6
    └── file7
ทำความสะอาดปลายทางไดเรกทอรีชั่วคราว
export historydir=/tmp/mail/dir  # Absolute path
rm -rf "$historydir"             # Caution when cleaning
ทำความสะอาดแหล่งที่มา repo ของคุณ
git commit ...           # Commit your working files
rm .gitignore            # Disable gitignore
git clean -n             # Simulate removal
git clean -f             # Remove untracked file
git checkout .gitignore  # Restore gitignore
แยกประวัติของแต่ละไฟล์ในรูปแบบอีเมล
cd my_repo/dirB
find -name .git -prune -o -type d -o -exec bash -c 'mkdir -p "$historydir/${0%/*}" && git log --pretty=email -p --stat --reverse --full-index --binary -- "$0" > "$historydir/$0"' {} ';'
แต่น่าเสียดายที่ตัวเลือก--followหรือไม่สามารถใช้ร่วมกับ--find-copies-harder --reverseนี่คือเหตุผลที่ประวัติถูกตัดเมื่อเปลี่ยนชื่อไฟล์ (หรือเมื่อเปลี่ยนชื่อไดเรกทอรีแม่)
หลัง: ประวัติชั่วคราวในรูปแบบอีเมล
/tmp/mail/dir
    ├── subdir
    │   ├── file3
    │   └── file4
    └── file5
2. จัดระเบียบไฟล์ต้นไม้ใหม่และอัปเดตการเปลี่ยนแปลงชื่อไฟล์ในประวัติ [ตัวเลือก]
สมมติว่าคุณต้องการย้ายไฟล์ทั้งสามนี้ใน repo อื่น (อาจเป็น repo เดียวกัน)
my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB              # New tree
│   ├── dirB1         # was subdir
│   │   ├── file33    # was file3
│   │   └── file44    # was file4
│   └── dirB2         # new dir
│        └── file5    # = file5
└── dirH
    └── file77
ดังนั้นจัดระเบียบไฟล์ของคุณใหม่:
cd /tmp/mail/dir
mkdir     dirB
mv subdir dirB/dirB1
mv dirB/dirB1/file3 dirB/dirB1/file33
mv dirB/dirB1/file4 dirB/dirB1/file44
mkdir    dirB/dirB2
mv file5 dirB/dirB2
ประวัติชั่วคราวของคุณคือตอนนี้:
/tmp/mail/dir
    └── dirB
        ├── dirB1
        │   ├── file33
        │   └── file44
        └── dirB2
             └── file5
เปลี่ยนชื่อไฟล์ในประวัติด้วย:
cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'
หมายเหตุ:สิ่งนี้จะเขียนประวัติเพื่อสะท้อนการเปลี่ยนแปลงของพา ธ และชื่อไฟล์ 
      (เช่นการเปลี่ยนตำแหน่ง / ชื่อใหม่ภายใน repo ใหม่)
3. ใช้ประวัติใหม่
ธุรกรรมซื้อคืนอื่น ๆ ของคุณคือ:
my_other_repo
├── dirF
│   ├── file55
│   └── file56
└── dirH
    └── file77
ใช้การคอมมิตจากไฟล์ประวัติชั่วคราว:
cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am 
repo อื่นของคุณคือตอนนี้:
my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB            ^
│   ├── dirB1       | New files
│   │   ├── file33  | with
│   │   └── file44  | history
│   └── dirB2       | kept
│        └── file5  v
└── dirH
    └── file77
ใช้git statusเพื่อดูจำนวนการกระทำที่พร้อมจะผลักดัน :-)
หมายเหตุ:เมื่อประวัติถูกเขียนใหม่เพื่อสะท้อนถึงการเปลี่ยนเส้นทางและชื่อไฟล์: 
      (เช่นเมื่อเปรียบเทียบกับตำแหน่ง / ชื่อภายใน repo หน้าที่แล้ว)
- ไม่จำเป็นต้องgit mvเปลี่ยนตำแหน่ง / ชื่อไฟล์
- ไม่จำเป็นต้องgit log --followเข้าถึงประวัติเต็ม
เคล็ดลับพิเศษ: ตรวจจับไฟล์ที่ถูกเปลี่ยนชื่อ / ย้ายภายใน repo ของคุณ
หากต้องการแสดงรายการไฟล์ที่ถูกเปลี่ยนชื่อ:
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'
การปรับแต่งเพิ่มเติมได้ที่: คุณสามารถดำเนินการคำสั่งgit logโดยใช้ตัวเลือกหรือ--find-copies-harder --reverseนอกจากนี้คุณยังสามารถลบสองคอลัมน์แรกโดยใช้cut -f3-และ grepping pattern ที่สมบูรณ์ '{. * =>. *}'
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'