यह उत्तर दिलचस्प कमांड प्रदान करता है 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
अपने रेपो स्रोत को साफ करें
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
इतिहास में फ़ाइल परिवर्तन और अद्यतन फ़ाइल नाम को बदलें [वैकल्पिक]
मान लीजिए आप इन तीन फाइलों को इस अन्य रेपो में स्थानांतरित करना चाहते हैं (वही रेपो हो सकता है)।
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"' {} ';'
नोट: यह पथ और फ़ाइल नाम के परिवर्तन को प्रतिबिंबित करने के लिए इतिहास को फिर से लिखता है।
(यानी नए रेपो के भीतर नए स्थान / नाम का परिवर्तन)
3. नया इतिहास लागू करें
आपका अन्य रेपो है:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
└── dirH
└── file77
अस्थायी इतिहास फ़ाइलों से लागू करें:
cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am
आपका अन्य रेपो अब है:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
├── dirB ^
│ ├── dirB1 | New files
│ │ ├── file33 | with
│ │ └── file44 | history
│ └── dirB2 | kept
│ └── file5 v
└── dirH
└── file77
git status
धकेले जाने के लिए तैयार कमिट की मात्रा देखने के लिए उपयोग करें :-)
नोट: जैसा कि इतिहास को पथ और फ़ाइल नाम परिवर्तन को प्रतिबिंबित करने के लिए फिर से लिखा गया है:
(यानी पिछले रेपो के भीतर स्थान / नाम की तुलना में)
git mv
स्थान / फ़ाइल नाम बदलने की आवश्यकता नहीं है ।
git log --follow
पूर्ण इतिहास तक पहुंचने की आवश्यकता नहीं है ।
एक्स्ट्रा ट्रिक: अपने रेपो के अंदर बदला हुआ / स्थानांतरित फ़ाइलों का पता लगाएँ
फ़ाइलों का नाम बदलने के लिए:
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'
अधिक अनुकूलन: आप git log
विकल्पों का उपयोग करके कमांड को पूरा कर सकते हैं --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 '{.* => .*}'