我看了一些参考文献,但仍然遇到问题:
SO:Pushing local branch to remote branch - gitpython
SO:Use GitPython to Checkout a new branch and push to remote
相关问题:https://github.com/gitpython-developers/GitPython/issues/471
教程:https://gitpython.readthedocs.io/en/stable/tutorial.html
我对Git的理解真的很基础,请耐心等待。我想克隆一个远程仓库,创建一个新分支,然后将新分支推回远程。
这似乎可行:
import git
import subprocess
nm_brnch = 'new_branch'
# Clone
repo_url = r'my_remote.git'
repo = git.Repo.clone_from(repo_url, dnm_wrk, branch=r'some_branch')
# Create new branch
git = repo.git
git.checkout('HEAD', b=nm_brnch)
# Push new branch to remote
subprocess.call(f'git push -u origin {nm_brnch}')
但这很丑:(。我试过这个没有成功:
repo.head.set_reference(nm_brnch)
repo.git.push("origin", nm_brnch)
答案 0 :(得分:1)
您必须定义一个远程仓库,然后再推送到它。例如
origin = repo.remote(name='origin')
origin.push()
有关更多推/拉示例,请参见Handling Remotes文档
答案 1 :(得分:0)
我在Python 3.7中使用gitpython==2.1.11
。以下是我的推送功能,在该功能中,我首先尝试进行高级推送,然后根据需要尝试进行低级推送。请注意我如何检查两个命令的返回值。我还记录了推送操作,这解释了每一步的情况。
class GitCommandError(Exception):
pass
class Git:
def _commit_and_push_repo(self) -> None:
repo = self._repo
remote = repo.remote()
remote_name = remote.name
branch_name = repo.active_branch.name
# Note: repo.index.entries was observed to also include unpushed files in addition to uncommitted files.
log.debug('Committing repository index in active branch "%s".', branch_name)
self._repo.index.commit('')
log.info('Committed repository index in active branch "%s".', branch_name)
def _is_pushed(push_info: git.remote.PushInfo) -> bool:
valid_flags = {push_info.FAST_FORWARD, push_info.NEW_HEAD} # UP_TO_DATE flag is intentionally skipped.
return push_info.flags in valid_flags # This check can require the use of & instead.
push_desc = f'active branch "{branch_name}" to repository remote "{remote_name}"'
log.debug('Pushing %s.', push_desc)
try:
push_info = remote.push()[0]
except git.exc.GitCommandError: # Could be due to no upstream branch.
log.warning('Failed to push %s. This could be due to no matching upstream branch.', push_desc)
log.info('Reattempting to push %s using a lower-level command which also sets upstream branch.', push_desc)
push_output = repo.git.push('--set-upstream', remote_name, branch_name)
log.info('Push output was: %s', push_output)
expected_msg = f"Branch '{branch_name}' set up to track remote branch '{branch_name}' from '{remote_name}'."
if push_output != expected_msg:
raise RepoPushError(f'Failed to push {push_desc}.')
else:
is_pushed = _is_pushed(push_info)
logger = log.debug if is_pushed else log.warning
logger('Push flags were %s and message was "%s".', push_info.flags, push_info.summary.strip())
if not is_pushed:
log.warning('Failed first attempt at pushing %s. A pull will be performed.', push_desc)
self._pull_repo()
log.info('Reattempting to push %s.', push_desc)
push_info = remote.push()[0]
is_pushed = _is_pushed(push_info)
logger = log.debug if is_pushed else log.error
logger('Push flags were %s and message was "%s".', push_info.flags, push_info.summary.strip())
if not is_pushed:
raise RepoPushError(f'Failed to push {push_desc} despite a pull.')
log.info('Pushed %s.', push_desc)
答案 2 :(得分:0)
扩展@Fraser的答案,这是我用来成功创建新分支的完整代码:
from pathlib import Path
# initialize repo and remote origin
repo_path = Path("~/git/sandboxes/git-sandbox").expanduser()
repo = git.Repo(repo_path)
origin = repo.remote(name="origin")
# create new head and get it tracked in the origin
repo.head.reference = repo.create_head(branch_name)
repo.head.reference.set_tracking_branch(origin.refs.master).checkout()
# create a file for the purposes of this example
touch[f"{repo_path}/tmp1.txt"] & plumbum.FG
# stage the changed file and commit it
repo.index.add("tmp1.txt")
repo.index.commit("mod tmp1.txt")
# push the staged commits
push_res = origin.push(branch_name)[0]
print(push_res.summary)