Objektif
- Gunakan (terinspirasi dari Smar , dipinjam dari Exherbo )
git am
- Tambahkan riwayat komit dari file yang disalin / dipindahkan
- Dari satu direktori ke direktori lainnya
- Atau dari satu repositori ke yang lain
Batasan
- Tag dan cabang tidak disimpan
- Histori terpotong pada nama file path (nama direktori)
Ringkasan
- Ekstrak riwayat dalam format email menggunakan
git log --pretty=email -p --reverse --full-index --binary
- Atur ulang pohon file dan perbarui nama file
- Tambahkan riwayat baru menggunakan
cat extracted-history | git am --committer-date-is-author-date
1. Ekstrak histori dalam format email
Contoh: Ekstrak riwayat file3
, file4
danfile5
my_repo
├── dirA
│ ├── file1
│ └── file2
├── dirB ^
│ ├── subdir | To be moved
│ │ ├── file3 | with history
│ │ └── file4 |
│ └── file5 v
└── dirC
├── file6
└── file7
Atur / bersihkan tujuan
export historydir=/tmp/mail/dir # Absolute path
rm -rf "$historydir" # Caution when cleaning the folder
Ekstrak riwayat setiap file dalam format email
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"' {} ';'
Sayangnya opsi --follow
atau --find-copies-harder
tidak dapat digabungkan dengan --reverse
. Inilah sebabnya mengapa sejarah dipotong ketika file diganti namanya (atau ketika direktori induk diubah namanya).
Riwayat sementara dalam format email:
/tmp/mail/dir
├── subdir
│ ├── file3
│ └── file4
└── file5
Dan Bonachea menyarankan untuk membalikkan loop dari perintah pembuatan git log pada langkah pertama ini: daripada menjalankan git log sekali per file, jalankan persis sekali dengan daftar file pada baris perintah dan buat satu log tunggal. Dengan cara ini komit yang memodifikasi banyak file tetap menjadi komit tunggal dalam hasil, dan semua komit baru mempertahankan urutan relatif aslinya. Catatan ini juga membutuhkan perubahan pada langkah kedua di bawah ini ketika menulis ulang nama file di log (sekarang disatukan).
2. Atur kembali pohon file dan perbarui nama file
Misalkan Anda ingin memindahkan ketiga file ini di repo lain ini (bisa menjadi repo yang sama).
my_other_repo
├── dirF
│ ├── file55
│ └── file56
├── dirB # New tree
│ ├── dirB1 # from subdir
│ │ ├── file33 # from file3
│ │ └── file44 # from file4
│ └── dirB2 # new dir
│ └── file5 # from file5
└── dirH
└── file77
Karena itu atur ulang file Anda:
cd /tmp/mail/dir
mkdir -p dirB/dirB1
mv subdir/file3 dirB/dirB1/file33
mv subdir/file4 dirB/dirB1/file44
mkdir -p dirB/dirB2
mv file5 dirB/dirB2
Riwayat sementara Anda sekarang:
/tmp/mail/dir
└── dirB
├── dirB1
│ ├── file33
│ └── file44
└── dirB2
└── file5
Ubah juga nama file dalam riwayat:
cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'
3. Terapkan sejarah baru
Repo Anda yang lain adalah:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
└── dirH
└── file77
Terapkan komit dari file riwayat sementara:
cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am --committer-date-is-author-date
--committer-date-is-author-date
mempertahankan stempel waktu komit asli ( komentar Dan Bonachea ).
Repo Anda yang lain sekarang:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
├── dirB
│ ├── dirB1
│ │ ├── file33
│ │ └── file44
│ └── dirB2
│ └── file5
└── dirH
└── file77
Gunakan git status
untuk melihat jumlah komit yang siap didorong :-)
Trik tambahan: Periksa file yang diubah namanya / dipindahkan dalam repo Anda
Untuk membuat daftar file yang telah diubah namanya:
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'
Kustomisasi lainnya: Anda dapat menyelesaikan perintah git log
menggunakan opsi --find-copies-harder
atau --reverse
. Anda juga dapat menghapus dua kolom pertama menggunakan cut -f3-
dan menangkap pola lengkap '{. * =>. *}'.
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'
git mv
: stackoverflow.com/questions/1094269/whats-the-purpose-of-git-mv