Я запускаю следующий MWE скрипта python, чтобы прочитать коммиты throw и создать еще один проект git в другом месте.

Я называю этот сценарий таким образом, чтобы перебрать проект git и создать еще один проект git под командой bash из

git filter-branch -f --tree-filter "python3 /media/sf_git/register-commits.py /home/mercury/splitted" --prune-empty --tag-name-filter cat -- --all

Аргумент для python3 - это сценарий, который запускается при каждой фиксации, а путь после него - это место, где предполагается создать проект B.

/media/sf_git/register-commits.py

import os
import sys


def git_init(module):
    os.system('git init ' + module)

def create_project(parent, module):
    os.chdir(parent)
    print('parent:', parent)
    git_init(module)
    if not os.path.exists(os.path.join(parent, module, '.git')):
        sys.exit('.git folder is not created.')


arg1 =  sys.argv[1]
if arg1 is None:
    sys.exit('The script argument is not provided')


commit_id = os.environ["GIT_COMMIT"]

module = 'projectB'
cwd = os.getcwd()

try:
    dst_module_path = os.path.join(arg1, module)
    if not os.path.exists(dst_module_path):
        create_project(arg1, module)
except Exception as e:
    print('Error: ' + str(e))
finally:
    os.chdir(cwd)

Проблема в том, что os.chdir может изменить путь. Я даже напечатал это. Это правильно. Но команда git init запускается в том же рабочем каталоге проекта A, а не проекта B. Это дает мне следующую ошибку

WARNING: git-filter-branch has a glut of gotchas generating mangled history
     rewrites.  Hit Ctrl-C before proceeding to abort, then use an
     alternative filtering tool such as 'git filter-repo'
     (https://github.com/newren/git-filter-repo/) instead.  See the
     filter-branch manual page for more details; to squelch this warning,
     set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

Rewrite 8a30d5630ab7ead31ecc3b30122054d27eec0dbe (1/3058) (0 seconds passed, remaining 0 predicted)
Reinitialized existing Git repository in /home/mercury/projectA/.git/
.git folder is not created.
parent: /home/mercury/splitted
tree filter failed: python3 /media/sf_git/register-commits.py /home/mercury/splitted

Он создает пустую папку projectB под /home/mercury/splitted без папки .git внутри нее.

Похоже, что есть еще одна побочная проблема, заключающаяся в изменении projectA. Потому что когда я запускаю скрипт во второй раз, возникает ошибка

Proceeding with filter-branch...

You need to run this command from the toplevel of the working tree.

Похоже, что проект пострадал. Единственный известный мне способ исправить это - скопировать папку .git проектаS из резервной копии.

Использование subprocess.Popen дает мне аналогичный результат:

def git_init(module):
    parent = os.getcwd()
    print('parent:', parent)
    proc = subprocess.Popen(['git', 'init', module], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=parent)
    p_status = proc.wait()
    (output, err) = proc.communicate()
    print(output)

Выход

WARNING: git-filter-branch has a glut of gotchas generating mangled history
     rewrites.  Hit Ctrl-C before proceeding to abort, then use an
     alternative filtering tool such as 'git filter-repo'
     (https://github.com/newren/git-filter-repo/) instead.  See the
     filter-branch manual page for more details; to squelch this warning,
     set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

Rewrite 8a30d5630ab7ead31ecc3b30122054d27eec0dbe (1/3058) (0 seconds passed, remaining 0 predicted)
parent: /home/mercury/splitted
parent: /home/mercury/splitted
b'Reinitialized existing Git repository in /home/mercury/projectA/.git/\n'
.git folder is not created.
tree filter failed: python3 /media/sf_git/register-commits.py /home/mercury/splitted

Странно, что git создает папку внутри /home/mercury/splitted, но пытается запустить .git под /home/mercury/projectA.

Когда я запускаю сценарии в обычной среде Python, все в порядке. Но под git filter-branch здесь пути не применяются к git, даже если рабочий каталог изменен нормально. Вдобавок похоже, что projectA повреждается, когда git init применяется к другому каталогу.

Я не уверен, является ли это проблемой git или python.

Что не так и как исправить эту проблему?

0
mercury 12 Фев 2021 в 10:34

1 ответ

Лучший ответ

Что не так ...

Есть две вещи, которые вы не должны делать с древовидным фильтром в git filter-branch, как правило:

  1. сменить рабочий каталог;
  2. используйте команды Git.

Это не обязательно эксклюзивный список, и, к счастью, есть несколько способов обойти эти два.

и как исправить эту проблему?

Ограничение на изменение каталогов на самом деле характерно для команд оболочки, выполняемых в оболочке верхнего уровня (filter-branch eval здесь ваш фильтр). Поскольку вы запускаете совершенно отдельный процесс, python, он позволяет вам изменять рабочий каталог. Но стоит упомянуть об этой проблеме, поскольку попытка оптимизировать ваш фильтр может привести к его возникновению.

Ограничение на использование команд Git связано с тем, что древовидный фильтр специально нацелен на то, чтобы позволить вам использовать команды non -Git для переделки содержимого каждой фиксации. Использование git filter-branch просто для проверки содержимого каждого коммита здесь не было целью.

К счастью, для запуска git init есть простой обходной путь: вам просто нужно удалить переменную среды GIT_DIR из среды при вызове Git. Если вы вызываете другие команды Git, возможно, вам придется отключить дополнительные переменные среды.

В целом, однако, непонятно, почему вы пытаетесь использовать для этого git filter-branch. Если вы хотите получить список коммитов, наиболее подходящим инструментом является git rev-list. Если вы хотите получить файлы из этих коммитов, все становится более сложным, но filter-branch все еще, вероятно, не тот инструмент.

0
torek 12 Фев 2021 в 21:29