คุณสามารถชำระเงินบางส่วนด้วยการโค่นล้มได้หรือไม่?


155

หากฉันมี 20 ไดเรกทอรีภายใต้ trunk / มีไฟล์จำนวนมากในแต่ละรายการและต้องการเพียง 3 ของไดเรกทอรีเหล่านั้นจะเป็นไปได้ไหมที่จะทำการชำระเงิน Subversion โดยมีเพียง 3 ไดเรกทอรีภายใต้ trunk


ดูเพิ่มเติมที่: stackoverflow.com/questions/1667986/…
Nakilon

คำตอบ:


78

การโค่นล้ม 1.5 แนะนำการชำระเงินแบบเบาบางซึ่งอาจเป็นสิ่งที่คุณอาจพบว่ามีประโยชน์ จากเอกสาร :

... ไดเรกทอรีที่กระจัดกระจาย (หรือเช็คเอาต์ตื้น ) ... ช่วยให้คุณสามารถตรวจสอบสำเนาการทำงาน - หรือบางส่วนของสำเนาการทำงาน - ตื้นกว่าการเรียกซ้ำที่เต็มไปด้วยความอิสระในการนำไฟล์และไดเรกทอรีย่อยที่ไม่สนใจก่อนหน้านี้ ในเวลาต่อมา


259

แน่นอนขอบคุณความคิดเห็นที่โพสต์ของฉันที่นี่ดูเหมือนว่าไดเรกทอรีกระจัดกระจายเป็นวิธีที่จะไป ฉันเชื่อว่าสิ่งต่อไปนี้ควรทำ:

svn checkout --depth empty http://svnserver/trunk/proj
svn update --set-depth infinity proj/foo
svn update --set-depth infinity proj/bar
svn update --set-depth infinity proj/baz

หรือ--depth immediatesแทนที่จะemptyเช็คเอาต์ไฟล์และไดเรกทอรีtrunk/projโดยไม่มีเนื้อหา ด้วยวิธีนี้คุณจะเห็นว่ามีไดเรกทอรีใดบ้างในที่เก็บ


ดังที่ได้กล่าวไว้ในคำตอบของ @ zigdon คุณสามารถชำระเงินแบบไม่เรียกซ้ำ นี่เป็นวิธีที่เก่ากว่าและยืดหยุ่นน้อยกว่าเพื่อให้ได้เอฟเฟกต์ที่คล้ายกัน:

svn checkout --non-recursive http://svnserver/trunk/proj
svn update trunk/foo
svn update trunk/bar
svn update trunk/baz

4
ถ้าฉันออกการปรับปรุง svn ในไดเรกทอรี trunk มันจะดึงโฟลเดอร์อื่น ๆ ทั้งหมดลงไปหรือเพียงแค่อัปเดตสิ่งที่ถูกดึงไปแล้ว?
Rob Walker

2
ฉันจะได้รับSkipped 'prom/foo'หลังจากsvn update --set-depth infinity proj/foo:(
sam

2
โอ้คุณต้องอัปเดตพาเรนต์ (proj / foo) ก่อนจึงจะอัปเดตได้ลึกขึ้น (proj / foo / boo)
แซม

4
นี่เป็นคำตอบที่ดีและควรเป็นคำตอบที่ถูกต้อง ขอขอบคุณ pkaeding!
Jimbo

1
คุณอาจจำเป็นต้องใช้ขั้นตอนกลางด้วยsvn update --set-depth immediates projเพื่อที่จะทำให้ proj / foo สำหรับการปรับปรุง
Craig

6

หรือทำการเช็คเอาต์ / trunk แบบไม่ต้องเรียกซ้ำจากนั้นให้ทำการอัพเดทด้วยตนเองใน 3 ไดเรกทอรีที่คุณต้องการ


6

ฉันเขียนสคริปต์เพื่อทำการเช็คเอาต์ที่ซับซ้อนโดยอัตโนมัติ

#!/usr/bin/env python

'''
This script makes a sparse checkout of an SVN tree in the current working directory.

Given a list of paths in an SVN repository, it will:
1. Checkout the common root directory
2. Update with depth=empty for intermediate directories
3. Update with depth=infinity for the leaf directories
'''

import os
import getpass
import pysvn

__author__ = "Karl Ostmo"
__date__ = "July 13, 2011"

# =============================================================================

# XXX The os.path.commonprefix() function does not behave as expected!
# See here: http://mail.python.org/pipermail/python-dev/2002-December/030947.html
# and here: http://nedbatchelder.com/blog/201003/whats_the_point_of_ospathcommonprefix.html
# and here (what ever happened?): http://bugs.python.org/issue400788
from itertools import takewhile
def allnamesequal(name):
    return all(n==name[0] for n in name[1:])

def commonprefix(paths, sep='/'):
    bydirectorylevels = zip(*[p.split(sep) for p in paths])
    return sep.join(x[0] for x in takewhile(allnamesequal, bydirectorylevels))

# =============================================================================
def getSvnClient(options):

    password = options.svn_password
    if not password:
        password = getpass.getpass('Enter SVN password for user "%s": ' % options.svn_username)

    client = pysvn.Client()
    client.callback_get_login = lambda realm, username, may_save: (True, options.svn_username, password, True)
    return client

# =============================================================================
def sparse_update_with_feedback(client, new_update_path):
    revision_list = client.update(new_update_path, depth=pysvn.depth.empty)

# =============================================================================
def sparse_checkout(options, client, repo_url, sparse_path, local_checkout_root):

    path_segments = sparse_path.split(os.sep)
    path_segments.reverse()

    # Update the middle path segments
    new_update_path = local_checkout_root
    while len(path_segments) > 1:
        path_segment = path_segments.pop()
        new_update_path = os.path.join(new_update_path, path_segment)
        sparse_update_with_feedback(client, new_update_path)
        if options.verbose:
            print "Added internal node:", path_segment

    # Update the leaf path segment, fully-recursive
    leaf_segment = path_segments.pop()
    new_update_path = os.path.join(new_update_path, leaf_segment)

    if options.verbose:
        print "Will now update with 'recursive':", new_update_path
    update_revision_list = client.update(new_update_path)

    if options.verbose:
        for revision in update_revision_list:
            print "- Finished updating %s to revision: %d" % (new_update_path, revision.number)

# =============================================================================
def group_sparse_checkout(options, client, repo_url, sparse_path_list, local_checkout_root):

    if not sparse_path_list:
        print "Nothing to do!"
        return

    checkout_path = None
    if len(sparse_path_list) > 1:
        checkout_path = commonprefix(sparse_path_list)
    else:
        checkout_path = sparse_path_list[0].split(os.sep)[0]



    root_checkout_url = os.path.join(repo_url, checkout_path).replace("\\", "/")
    revision = client.checkout(root_checkout_url, local_checkout_root, depth=pysvn.depth.empty)

    checkout_path_segments = checkout_path.split(os.sep)
    for sparse_path in sparse_path_list:

        # Remove the leading path segments
        path_segments = sparse_path.split(os.sep)
        start_segment_index = 0
        for i, segment in enumerate(checkout_path_segments):
            if segment == path_segments[i]:
                start_segment_index += 1
            else:
                break

        pruned_path = os.sep.join(path_segments[start_segment_index:])
        sparse_checkout(options, client, repo_url, pruned_path, local_checkout_root)

# =============================================================================
if __name__ == "__main__":

    from optparse import OptionParser
    usage = """%prog  [path2] [more paths...]"""

    default_repo_url = "http://svn.example.com/MyRepository"
    default_checkout_path = "sparse_trunk"

    parser = OptionParser(usage)
    parser.add_option("-r", "--repo_url", type="str", default=default_repo_url, dest="repo_url", help='Repository URL (default: "%s")' % default_repo_url)
    parser.add_option("-l", "--local_path", type="str", default=default_checkout_path, dest="local_path", help='Local checkout path (default: "%s")' % default_checkout_path)

    default_username = getpass.getuser()
    parser.add_option("-u", "--username", type="str", default=default_username, dest="svn_username", help='SVN login username (default: "%s")' % default_username)
    parser.add_option("-p", "--password", type="str", dest="svn_password", help="SVN login password")

    parser.add_option("-v", "--verbose", action="store_true", default=False, dest="verbose", help="Verbose output")
    (options, args) = parser.parse_args()

    client = getSvnClient(options)
    group_sparse_checkout(
        options,
        client,
        options.repo_url,
        map(os.path.relpath, args),
        options.local_path)

0

หากคุณมีสำเนาภายในเครื่องอยู่แล้วคุณสามารถลบโฟลเดอร์ย่อยที่ไม่ต้องการได้โดยใช้--set-depthคำสั่ง

svn update --set-depth=exclude www

ดู: http://blogs.collab.net/subversion/sparse-directories-now-with-exclusion

set-depthเส้นทาง multipile สนับสนุนคำสั่ง

การอัพเดตสำเนาโลคัลรูทจะไม่เปลี่ยนความลึกของโฟลเดอร์ที่แก้ไข

หากต้องการคืนค่าโฟลเดอร์ให้เป็นการตรวจสอบซ้ำคุณสามารถใช้--set-depthอีกครั้งกับพารามิเตอร์อนันต์

svn update --set-depth=infinity www

-1

เรียงจาก ในฐานะที่เป็นบ๊อบบี้พูดว่า:

svn co file:///.../trunk/foo file:///.../trunk/bar file:///.../trunk/hum

จะได้รับโฟลเดอร์ แต่คุณจะได้รับโฟลเดอร์แยกจากมุมมองการโค่นล้ม คุณจะต้องแยกข้อผูกพันและการอัปเดตในแต่ละโฟลเดอร์ย่อย

ฉันไม่เชื่อว่าคุณสามารถชำระเงินต้นไม้บางส่วนแล้วทำงานกับต้นไม้บางส่วนเป็นนิติบุคคลเดียว


-10

ไม่ได้อยู่ในวิธีที่มีประโยชน์โดยเฉพาะอย่างยิ่งไม่ คุณสามารถตรวจสอบ subtrees (ตามคำแนะนำของ Bobby Jack) แต่จากนั้นคุณจะสูญเสียความสามารถในการอัปเดต / ส่งข้อมูลแบบอะตอม ในการทำเช่นนั้นพวกเขาจะต้องอยู่ภายใต้ผู้ปกครองทั่วไปและทันทีที่คุณตรวจสอบผู้ปกครองทั่วไปคุณจะดาวน์โหลดทุกอย่างภายใต้ผู้ปกครองนั้น ไม่ใช่แบบเรียกซ้ำไม่ได้เป็นตัวเลือกที่ดีเพราะคุณต้องการอัปเดตและยืนยันว่าจะเรียกซ้ำ


16
-1 สำหรับคำตอบที่ผิด มีกรณีการใช้งานมากมายในชีวิตจริงที่คุณต้องการทำงานในส่วนประกอบย่อยเพียงส่วนเล็กในโครงการขนาดใหญ่และคุณไม่ต้องการตรวจสอบโครงการทั้งหมด
ปีเตอร์

สาเหตุที่ทำให้คุณสามารถทำงานกับ subtrees เหล่านี้ได้อย่างอิสระต่อกัน แต่ฉันคิดว่า DrPizza มีความหมายว่าไม่ใช่การคอมมิท / คอมมิชชันในกรณีนี้ และมันอาจเป็นปัญหาในสภาพที่แน่นอน
Andry
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.