2014-10-05 46 views
1

git的一個煩惱是不得不使用git remote add upstream URL來製作從某些上游回購(例如Github分叉)派生的回購庫的每個克隆。理想情況下,我應該能夠將上游位置存儲在分叉回購本身中,以便所有克隆自動設置它。有沒有辦法用git來完成這個任務?如何永久添加上游位置到git repo?

+0

我不確定我是否理解您的問題。正如Andrew所指出的那樣,默認情況下,一個克隆的回購庫(以「origin」的名字)知道它從中克隆的遠端。你想讓這個名字成爲「上游」而不是(在這種情況下,你應該看看安德魯的答案),還是你想在克隆時添加第二個遙控器? – Jubobs 2014-10-05 15:18:35

+1

添加第二個遠程指向原始回購點的起源。我在這個問題上澄清了這一點。感謝您指出歧義! – holocronweaver 2014-10-05 15:24:24

回答

2

正如其他答案所述,git目前沒有內置功能來將repos連接在一起。

因此,我編寫了一個名爲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., [email protected] or [email protected]).') 
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 ('[email protected]' in origin): 
    ext = '.git' 
    clone = 'git clone %s %s' 
    setUpstream = 'git remote add upstream %s' 
elif ('[email protected]' 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() 
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的包裝,但必須對每個存儲庫進行硬編碼。

2

就Git本身而言,原始回購(即您從中分出的回購)與您的分支克隆之間沒有任何關聯;後者沒有關於前者URL的信息。因此,無論如何,您必須在克隆後將原始回購添加爲克隆的遠程回收。

要自動化的東西一點點,並避免鍵入網址的每一次,你可以只爲您定義從分叉每個項目一個別名:

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

克隆刀叉後,你將不得不cd內新克隆並記得調用相應的別名。

以自動化一步將涉及編寫某種包裝的周圍git clone那會自動cd克隆內部並運行git remote add...,但解析git clone的論點正確可能有點太複雜了。