[英]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
中的树形过滤器中有两件事您不能做:
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.