Bu cevap git am
, adım adım örneklerle dayalı ve sunulan ilginç komutlar sağlar .
Amaç
- Dosyaların bir kısmını veya tamamını bir havuzdan diğerine taşımak istiyorsunuz.
- Onların geçmişini korumak istiyorsun.
- Ancak etiketleri ve dalları tutmayı umursamazsınız.
- Yeniden adlandırılmış dosyalar (ve yeniden adlandırılmış dizinlerdeki dosyalar) için sınırlı geçmişi kabul edersiniz.
prosedür
- Kullanarak geçmişi e-posta biçiminde ayıklayın
git log --pretty=email -p --reverse --full-index --binary
- Dosya ağacını yeniden düzenleyin ve geçmişte dosya adı değişikliğini güncelleyin [isteğe bağlı]
- Kullanarak yeni geçmiş uygula
git am
1. Geçmişi e-posta biçiminde ayıklayın
Örnek: hulasası geçmişi file3
, file4
vefile5
my_repo
├── dirA
│ ├── file1
│ └── file2
├── dirB ^
│ ├── subdir | To be moved
│ │ ├── file3 | with history
│ │ └── file4 |
│ └── file5 v
└── dirC
├── file6
└── file7
Geçici dizin hedefini temizleme
export historydir=/tmp/mail/dir # Absolute path
rm -rf "$historydir" # Caution when cleaning
Repo kaynağınızı temizleyin
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
Her dosyanın geçmişini e-posta biçiminde ayıklayın
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"' {} ';'
Ne yazık ki seçenek --follow
veya --find-copies-harder
birleştirilemez --reverse
. Dosya yeniden adlandırıldığında (veya bir üst dizin yeniden adlandırıldığında) geçmişin kesilmesinin nedeni budur.
Sonra: E-posta biçiminde geçici geçmiş
/tmp/mail/dir
├── subdir
│ ├── file3
│ └── file4
└── file5
2. Dosya ağacını yeniden düzenleyin ve geçmişte dosya adı değişikliğini güncelleyin [isteğe bağlı]
Bu üç dosyayı başka bir repoda taşımak istediğinizi varsayalım (aynı repo olabilir).
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
Bu nedenle dosyalarınızı yeniden düzenleyin:
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
Geçici geçmişiniz şimdi:
/tmp/mail/dir
└── dirB
├── dirB1
│ ├── file33
│ └── file44
└── dirB2
└── file5
Geçmişteki dosya adlarını da değiştirin:
cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'
Not: Bu, yol ve dosya adı değişikliğini yansıtacak şekilde geçmişi yeniden yazar.
(örneğin, yeni repodaki yeni konumun / adın değiştirilmesi)
3. Yeni geçmiş uygulayın
Diğer repo:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
└── dirH
└── file77
Geçici geçmiş dosyalarından taahhütleri uygula:
cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am
Diğer repo şimdi:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
├── dirB ^
│ ├── dirB1 | New files
│ │ ├── file33 | with
│ │ └── file44 | history
│ └── dirB2 | kept
│ └── file5 v
└── dirH
└── file77
kullanım git status
hazır taahhüt miktarını görmek için :-)
Not: Geçmiş, yolu ve dosya adı değişikliğini yansıtacak şekilde yeniden yazıldığı için:
(yani önceki repodaki konum / adla karşılaştırıldığında)
git mv
Konum / dosya adını değiştirmenize gerek yoktur .
git log --follow
Tam geçmişe erişmeye gerek yok .
Ek numara: Reponuz içindeki yeniden adlandırılmış / taşınmış dosyaları tespit edin
Yeniden adlandırılan dosyaları listelemek için:
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'
Daha fazla özelleştirme: veya git log
seçeneklerini kullanarak komutu tamamlayabilirsiniz . İlk iki sütunu, '{. * =>. *}' Deseninin tamamını kullanarak ve selamlayarak da kaldırabilirsiniz .--find-copies-harder
--reverse
cut -f3-
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'