2017-02-20 36 views
0

Предположим, я хочу переписать историю Git, перемещая все содержимое /foo/bar до /baz/quux для всех прошлых коммитов; работает в Windows.git filter-branch: перемещение папки с -index-фильтром не работает

Я сделал образец репо с двумя фиксаций в /foo/bar и больше ничего:

git clone https://github.com/jakub-g/filter-branch-test 

Давайте положить сценарий, как показано ниже одной папки от моего Git репо и запустить его (подобные вещи упоминаются во многих местах SO, включая https://stackoverflow.com/a/13590229).

#!/bin/bash 
PATH_TO_GIT_REPO='./filter-branch-test' 
REWRITE_FROM='foo/bar/' 
REWRITE_TO='baz/quux/' 

cd ${PATH_TO_GIT_REPO} && 
git filter-branch -f --index-filter \ 
'git ls-files -s | sed "s-\t${REWRITE_FROM}-\t${REWRITE_TO}-" \ 
    | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info \ 
    && mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' && 
cd - 

Когда я запускаю его:

bash ./runFilterBranch.sh 

Выход:

... 
WARNING: Ref 'refs/heads/master' is unchanged 

и ничего не случилось, я до сих пор есть старые пути.

Когда я запустил git ls-files -s | sed "s-\t${REWRITE_FROM}-\t${REWRITE_TO}-" в мастер, я вижу, что sed правильно выполняет замены.

Что мне здесь не хватает?

+1

Очевидная проблема в том, что '$ {REWRITE_FROM}' и '$ {REWRITE_TO}' не будет расширяться на месте здесь весь индекс фильтра заключен в одинарные кавычки. Другая потенциальная проблема заключается в том, работает ли здесь '\ t' (я не знаю, работает ли это в' sed', который вы используете). – torek

+0

Да, проблема была связана с одинарными кавычками, предотвращающими расширение. Похоже, пришло время поспать! –

ответ

0

Как @torek упоминалось выше, проблема была основная проблема с переменными разложения не происходит в одинарные кавычки.

Просто для записи, вот как я обновил свой сценарий для повторного использования и, чтобы иметь возможность передавать переменные извне (переменная расширения и ускользает хитра)

На самом деле я создал две функции Баша на 2 различные варианты использования, вторая - быстрее для определенных сценариев.

PATH_TO_GIT_REPO='test-folder' 
REWRITE_FROM='foo/bar/' 
REWRITE_TO='baz/quux/' 

# Rewrite just one folder and keep all the other folder intact. 
# Note this will rewrite ALL the commits in the git repo's history 
# so it will be slow for big repos. 
rewriteFolder(){ 
    SED_COMMAND='s-\t\"*'${REWRITE_FROM}'-\t'${REWRITE_TO}'-' 

    cd ${PATH_TO_GIT_REPO} && 
    git branch -f FILTER_BRANCH_BACKUP && 
    git filter-branch -f --index-filter \ 
    "git ls-files -s | sed \"$SED_COMMAND\" | 
     GIT_INDEX_FILE=\$GIT_INDEX_FILE.new git update-index --index-info && 
     mv \$GIT_INDEX_FILE.new \$GIT_INDEX_FILE" HEAD 
} 

# Rewrite just one folder and isolate it (remove all the other folders). 
# If you have a big number of commits, and only some of them touch ${REWRITE_FROM}, 
# this will rewrite only this small subset of commits, and discard all the other commits, 
# hence it will be much faster than `rewriteFolder`. 
isolateAndRewriteFolder(){ 
    SED_COMMAND='s-\t\"*-\t'${REWRITE_TO}'-' 

    cd ${PATH_TO_GIT_REPO} && 
    git branch -f FILTER_BRANCH_BACKUP && 
    echo 'Step 1/2...' && 
    git filter-branch -f --prune-empty --subdirectory-filter ${REWRITE_FROM} && 
    echo 'Step 2/2...' && 
    git filter-branch -f --index-filter \ 
    "git ls-files -s | sed \"$SED_COMMAND\" | 
     GIT_INDEX_FILE=\$GIT_INDEX_FILE.new git update-index --index-info && 
     mv \$GIT_INDEX_FILE.new \$GIT_INDEX_FILE" HEAD  
} 
2

Кстати, есть более простой способ сделать это:

git filter-branch --index-filter " 
     git read-tree --prefix='$REWRITE_TO'/ \$GIT_COMMIT:'$REWRITE_FROM' 
     git rm -r --cached '$REWRITE_FROM' 
" 
+0

, похоже, тоже работает, хотя мне пришлось удалить конечную косую черту в '' $ REWRITE_TO '/ '(у меня уже есть косая черта в моей переменной, и здесь слэш будет передан после закрытия апострофа), спасибо –

 Смежные вопросы

  • Нет связанных вопросов^_^