简体   繁体   English

git 过滤器分支调用的 python 脚本下的 git init 使用错误的目录

[英]git init under python script called by git filter-branch uses wrong directory

I run the following MWE of python script to read throw commits and create another git projec somewhere else.我运行 python 脚本的以下 MWE 来读取 throw 提交并在其他地方创建另一个 git 项目。

I call this script this way to iterate through git projectA and create another git projectB under bash command of我以这种方式调用此脚本来遍历 git projectA 并在 bash 命令下创建另一个 git projectB

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

The argument to python3 is the script that runs on each commit and the path after it is the location where project B is supposed to be created. python3的参数是在每次提交时运行的脚本,它之后的路径是应该创建项目 B 的位置。

/media/sf_git/register-commits.py /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)

The problem is that the os.chdir can change the path.问题是os.chdir可以更改路径。 I have even printed it.我什至已经打印出来了。 That's correct.这是正确的。 But the git init command runs in the same working directory of project A instead of project B. It gives me the following error但是 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

It creates an empty folder projectB under /home/mercury/splitted with no .git folder inside it.它在/home/mercury/splitted splitted 下创建一个空文件夹projectB ,其中没有.git文件夹。

It looks like that there is another side problem that the projectA is changed.看起来还有另一个问题是项目A被改变了。 Because when I run the script for the second time, there is an error因为当我第二次运行脚本时,出现了错误

Proceeding with filter-branch...

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

It looks like the projectA is hurt.看起来项目A受到了伤害。 The only way to fix that I know is to copy .git folder of projectA from the backup.我知道的唯一解决方法是从备份中复制.git的 .git 文件夹。

Using subprocess.Popen gives me a similar result:使用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)

output 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

This is strange that git creates a folder inside /home/mercury/splitted but tries initiating the .git under /home/mercury/projectA .奇怪的是 git 在/home/mercury/splitted splitted 内创建了一个文件夹,但尝试在/home/mercury/projectA .git

When I run the scripts under normal python environment, everything is fine.当我在正常的 python 环境下运行脚本时,一切都很好。 But under git filter-branch here the paths do not apply to git even though the working directory is changed fine.但是在git filter-branch下,即使工作目录更改得很好,路径也不适用于git In addition to that, it looks like projectA gets corrupted when git init is applied for another directory.除此之外,当git init应用于另一个目录时,projectA 似乎已损坏。

I am not sure exactly if this is a git problem or python problem.我不确定这是git问题还是python问题。

What is wrong and how to fix this problem?出了什么问题以及如何解决此问题?

What is wrong...怎么了...

There are two things you must not do in a tree filter, in git filter-branch , in general:一般来说,在git filter-branch中的树形过滤器中有两件事您不能做:

  1. change the working directory;更改工作目录;
  2. use Git commands.使用 Git 命令。

This is not necessarily an exclusive list, and, luckily, there are some ways around these two.这不一定是一个独家列表,幸运的是,有一些方法可以解决这两个问题。

and how to fix this problem?以及如何解决这个问题?

The limitation on changing directories is actually specific to shell commands run in the top level shell (filter-branch eval s your filter here).更改目录的限制实际上特定于shell 命令在顶级 shell 中运行(filter-branch eval是您的过滤器)。 Since you're firing up a completely separate process, python , that allows you to change the working directory.由于您正在启动一个完全独立的进程python ,因此您可以更改工作目录。 But it's worth mentioning the issue, since an attempt to optimize your filter might result in running into it.但值得一提的是这个问题,因为尝试优化您的过滤器可能会导致遇到它。

The limitation on using Git commands is because a tree filter is specifically aimed at letting you use non -Git commands to rework the contents of each commit.使用 Git 命令的限制是因为树过滤器专门用于让您使用-Git 命令重新处理每个提交的内容 Using git filter-branch simply to examine the contents of each commit wasn't the intent here.使用git filter-branch检查每个提交的内容并不是这里的意图。

Fortunately, there is a simple workaround for running git init like this: you just need to remove the environment variable GIT_DIR from the environment when you invoke Git.幸运的是,有一个简单的解决方法可以像这样运行git init :您只需在调用 Git 时从环境中删除环境变量GIT_DIR If you invoke other Git commands there may be more environment variables you must unset.如果您调用其他 Git 命令,则可能需要取消设置更多环境变量。

Overall, though, it's not clear why you're trying to use git filter-branch for this.不过,总体而言,尚不清楚您为什么要为此尝试使用git filter-branch If you want to get a list of commits, the correct tool is usually git rev-list .如果要获取提交列表,正确的工具通常是git rev-list If you want to get files from those commits, things get more complex, but filter-branch is still probably not the right tool.如果您想这些提交中获取文件,事情会变得更加复杂,但 filter-branch 可能仍然不是正确的工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM