如何将上游位置永久添加到git repo?

时间:2014-10-05 15:03:18

标签: git

git的一个烦恼是必须使用git remote add upstream URL来制作一个从一些上游仓库(例如Github forks)分叉的repo的每个克隆。理想情况下,我应该能够将上游位置存储在forked repo本身中,以便所有克隆自动设置它。有没有办法用git完成这个?

3 个答案:

答案 0 :(得分:2)

就Git本身而言,原始仓库(即你分叉的仓库)与你的叉子的克隆之间没有联系;后者不包含有关前者URL的信息。因此,无论如何,您必须在克隆之后将原始仓库添加为克隆的远程。

为了使事情自动化并避免每次都输入URL,您只需为分叉的每个项目定义一个别名:

git config alias.remaddfoo "remote add upstream <URL-of-original-project-foo>"

克隆你的fork后,你必须在新克隆中cd并记住调用相应的别名。

进一步采取自动化将涉及在git clone周围编写某种包装器,它将自动cd在克隆内并运行git remote add...,但解析git clone&#39正确的论证可能有点过于复杂。

答案 1 :(得分:2)

正如其他答案所述,git目前没有将repos链接在一起的内置功能。<​​/ p>

因此,我编写了一个名为clone的小型Python脚本,它使用BeatifulSoup 4解析BitBucket和GitHub的上游存储库,并将其添加为名为upstream的远程数据库。这适用于git和Mercurial。它是hosted on GitHub,但为了完成,我在这个答案中包含了完整的脚本:

#! /usr/bin/env python3
description='''
A wrapper for repo cloning commands for various DVCS.
Automatically adds the upstream URL when cloning a forked repo from
popular DVCS web hosts.
Currently supports:
 (DVCS: git, Mercurial)
 (hosts: GitHub, Bitbucket)
'''
# Created by Jesse Johnson a.k.a. holocronweaver (2014-10-08).
import argparse
import re
import subprocess
import urllib.request

from bs4 import BeautifulSoup

def find(regex, string, errorMessage):
    '''Return value at regex, or else print error message and exit program.'''
    m = re.search(regex, string)
    if (m):
        return m.group(1)
    else:
        print('Error:', errorMessage)
        exit()

parser = argparse.ArgumentParser(description=description)
parser.add_argument('origin', metavar='O', type=str,
                    help='the SSH URL of origin repo, optionally'
                    'followed by its destination folder')
args = parser.parse_args()

# Parse destination.
splitArgs = re.split('\s+', args.origin)
if len(splitArgs) > 1:
    origin = splitArgs[0]
    destination = splitArgs[1]
else:
    origin = args.origin
    destination = find('@.*\.\w+[:|/].*/(.*)[.git]?$', origin,
                            'Error: Could not parse destination folder from origin URL.')
    destination = re.sub('\.git', '', destination)
print('destination folder:', destination)

# Unfortunately HTTPS URLs do not contain enough info to clarify which
# DVCS is being used, so SSH is easiest to support.
vcs = find('^[ssh://]?(.*)@', origin,
           'URL does not contain SSH user (e.g., git@ or hg@).')
print('version control system:', vcs)

domain = find('@(.*\.\w+)[:|/]', origin,
              'Error: Could not parse domain from origin URL.')
print('domain:', domain)

path = find('@.*\.\w+([:|/].*)[.git]?$', origin,
         'Error: Could not parse repo path from origin URL.')
path = re.sub(':', '/', path)
print('repo path:', path)

homepage = 'https://' + domain + path
print(homepage)

data = urllib.request.urlopen(homepage).read()
soup = BeautifulSoup(data)

# Version control system specifics.
if ('git@' in origin):
    ext = '.git'
    clone = 'git clone %s %s'
    setUpstream = 'git remote add upstream %s'
elif ('hg@' in origin):
    ext = ''
    clone = 'hg clone %s %s'
    setUpstream = 'echo "upstream = %s \n" >> .hg/hgrc'
else:
    print('Error: Version control system not supported.')
    exit()

upstream = None
if ('github.com' in origin):
    element = soup.find('span', class_='fork-flag')
    if element:
        upstreamBase = element.span.a['href']
        upstream = 'https://github.com' + upstreamBase + ext
elif ('bitbucket.org' in origin):
    element = soup.find('a', class_='fork-of')
    if element:
        upstreamBase = element['href']
        upstream = 'https://bitbucket.org' + upstreamBase + ext
else:
    print('Warning: Web host not supported.')
    print('Warning: Continuing to clone without adding upstream repo.')

print(upstream)

subprocess.Popen(clone % (origin, destination), shell=True).wait()
if upstream:
    subprocess.Popen(setUpstream % upstream, cwd=destination, shell=True).wait()

答案 2 :(得分:1)

默认情况下git clone会调用您的远程“来源”。如果你想让它被称为其他东西,请使用

git clone -o upstream <path_to_repo>

Git Clone

--origin <name>
-o <name>
Instead of using the remote name origin to keep track of the upstream repository, use <name>.

编辑:对于需要跟踪遥控器遥控器的情况......我从来没有找到一个好方法来做到这一点。您可以在git clone周围编写一个包装器,但必须对每个存储库进行硬编码。