Об'єктивна
- Використання (натхнене у Smar , запозичене у Exherbo )
git am
- Додати історію фіксації скопійованих / переміщених файлів
- З одного каталогу в інший
- Або з одного сховища в інше
Обмеження
- Теги та гілки не зберігаються
- Історія скорочується при перейменуванні файлу шляху (перейменування каталогу)
Підсумок
- Витягнути історію у форматі електронної пошти за допомогою
git log --pretty=email -p --reverse --full-index --binary
- Реорганізуйте дерево файлів та оновіть назви файлів
- Додайте нову історію за допомогою
cat extracted-history | git am --committer-date-is-author-date
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 the folder
Витягування історії кожного файлу у форматі електронної пошти
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
На цьому першому кроці Дон Бонахея пропонує інвертувати петлі команди генерування журналу git: замість того, щоб запускати журнал git один раз на файл, запустіть його рівно один раз зі списком файлів у командному рядку та генеруйте єдиний єдиний журнал. Таким чином, коміти, які змінюють декілька файлів, залишаються одним результатом у результаті, а всі нові комітети підтримують свій початковий відносний порядок. Зауважте, що це також потребує змін на другому кроці нижче, коли переписуються імена файлів у (тепер уніфікований) журнал.
2. Реорганізуйте дерево файлів та оновіть назви файлів
Припустимо, ви хочете перемістити ці три файли в інший репо-файл (може бути тим же репо).
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
Тому реорганізуйте свої файли:
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
Зараз ваша тимчасова історія:
/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 --committer-date-is-author-date
--committer-date-is-author-date
зберігає оригінальні часові позначки на комісію (коментар Дана Бонахеї ).
Ваше інше репо тепер:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
├── dirB
│ ├── dirB1
│ │ ├── file33
│ │ └── file44
│ └── dirB2
│ └── file5
└── dirH
└── file77
Використовуйте git status
для перегляду кількості комісій, готових до надсилання :-)
Додатковий фокус: Перевірте перейменовані / переміщені файли в межах репо
Щоб перелічити перейменовані файли:
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 '{.* => .*}'
git mv
: stackoverflow.com/questions/1094269/whats-the-purpose-of-git-mv