2009-02-14 25 views
49

Tôi đang xem xét sử dụng git trên quy mô lớn. Tôi đã hy vọng tăng cường nhận con nuôi và làm cho mọi thứ trở nên dễ dàng hơn bằng cách gọi thân cây nhánh chính.Có thể đặt bí danh một chi nhánh trong Git không?

Điều này có thể và sẽ mang đến cho người dùng SVN một số cảm giác thoải mái. Tôi biết tôi có thể tạo ra một chi nhánh được gọi là thân cây nhưng điều đó dường như đi chệch khỏi các tiêu chuẩn git và có thể gây ra một số người dùng bị lẫn lộn.

Tôi biết rằng tôi cũng có thể tạo và xóa thẻ cho nội dung của trái tim nhưng khi tôi kiểm tra các thẻ đó, nó cho tôi biết đó là một chi nhánh không phải là địa phương, nhưng có lẽ không phải là điều tôi muốn làm.

Tôi là tổng git newb nhưng là chuyên gia dày dặn tại các hệ thống phát hành và xây dựng.

Điều tôi muốn làm là có thể gọi chính trunk. Tôi đã thấy khả năng các lệnh bí danh có áp dụng cho tên của các đối tượng được phiên bản không?

Tôi biết git-svn tồn tại và các công cụ khác nhưng chi phí của hệ thống kho lưu trữ lớp làm tôi sợ.

Trả lời

63

Bạn có thể đổi tên nhánh chính như Greg đã đề xuất hoặc bạn cũng có thể tạo một thân cây là tham chiếu tượng trưng cho nhánh chính để cả người dùng git và svn có nhánh 'chính' mà họ đã quen .

git symbolic-ref refs/heads/trunk refs/heads/master 

Lưu ý rằng thân cây không phải là công dân hạng nhất. Nếu bạn thanh toán trunk và thực hiện git status, bạn sẽ thực sự ở trên master, tuy nhiên bạn có thể sử dụng lệnh trunk ở tất cả các địa điểm mà bạn sử dụng tên chi nhánh (nhật ký, hợp nhất, v.v.).

+0

Phục vụ cả hai loại người dùng là mối quan tâm chính của tôi. Làm điều này trên máy chủ đủ cho bí danh thực sự có thể nhìn thấy hoàn toàn? Tôi sẽ bỏ phiếu cho bạn bởi tôi chưa có tin cho nó. – ojblass

+0

Vâng, đúng thế. Khi người dùng git fetch, họ sẽ thấy một ref từ xa cho cả origin/master và origin/trunk. Nó sẽ không nhất thiết phải rõ ràng từ việc lấy chúng là giống nhau, nhưng khi bất cứ ai đẩy tới chủ hoặc thân cây thì cả hai nhánh sẽ 'kỳ diệu' được cập nhật cùng nhau. –

+1

Tôi không nghĩ rằng symrefs chuyển sang bản sao nếu sử dụng giao thức git: // hoặc ssh - bạn nên kiểm tra nó. –

9

Không có gì đặc biệt về tên "chính" trong Git, nó chỉ được gọi là theo quy ước (và theo mặc định). Bạn chắc chắn có thể gọi nó là "thân cây" nếu bạn thích:

git branch -m master trunk 

Điều này cũng giống như Subversion, trong đó tên "trunk" chỉ được gọi theo quy ước. Bạn có thể gọi là nhánh chính "master" trong Subversion.

+0

Mà không biết ước mới sẽ Cảo mới không biết phải bắt đầu từ đâu? – ojblass

+0

HEAD của kho lưu trữ chung sẽ trỏ đến "trunk", do đó các trình kéo sẽ không phải biết. –

3

git-branch-alias kịch bản (và tính năng theo yêu cầu):
http://www.mail-archive.com/git%40vger.kernel.org/msg49171.html

Đây là một wrapper an toàn xung quanh các kỹ thuật thể hiện trong câu trả lời của Charles Bailey.

$ git branch-alias short some-overly-long-branch-name # creates alias 
$ git branch-alias short # creates alias for current branch 
$ git log short 
$ git checkout short 
$ git push origin short # pushes the branch, not the alias/reference 
$ git branch-alias --delete short 

Cập nhật phiên bản dành cho thử nghiệm:

#!/bin/sh 
# git branch-alias 
# Version 1.09-rc1 
# Author: Phil S. 

# Creates branch aliases, so that you can refer to a long branch name 
# by a convenient short alias. This is just a "do what I mean" wrapper 
# around git symbolic-ref, but without the (considerable) risk of 
# trashing a branch if you get your arguments wrong 

# Examples: 
# git branch-alias short some-overly-long-branch-name # creates alias 
# git branch-alias short # creates alias for current branch 
# git log short 
# git checkout short 
# git push origin short # pushes the branch, not the alias/reference 
# git branch-alias --delete short 

# Caveats: 
# Although everything else I've tried works seamlessly, I note that 
# git merge <alias> will cause the alias name to be mentioned in the 
# commit message, rather than the real branch. It would be nicer if 
# the branch name appeared. 

# Compatibility: 
# Originally developed with git version 1.7.12.4 
# Tested with git versions 1.9.0, 2.54, 2.80 
# 
# Related git changes between versions 1.7.12.4 and 1.9.0: 
# 
# 1.8.0.1 
# * A symbolic ref refs/heads/SYM was not correctly removed with "git 
# branch -d SYM"; the command removed the ref pointed by SYM 
# instead. 
# 
# 1.8.1 
# * "git symbolic-ref" learned the "-d $symref" option to delete the 
# named symbolic ref, which is more intuitive way to spell it than 
# "update-ref -d --no-deref $symref". 

# Change Log: 
# v1.09: 
# POSIX-compatible option handling and output. 
# 
# v1.08: 
# Removed test git show-ref --verify --heads --quiet "refs/heads/${symref}" 
# for asserting that the specified reference was valid before deleting a 
# reference, as we need to permit the deletion of references to branches 
# which have /already/ been deleted, and this test prevented that. 
# n.b. We already had another validation test to fall back on, using 
# git symbolic-ref "refs/heads/${symref}" 
# 
# v1.07: 
# Minor tweaks. Posted as feature-request to git mailing list: 
# http://www.mail-archive.com/git%40vger.kernel.org/msg49171.html 
# Also appears at the following gmane.org URL, but there the code is broken 
# by an email obfuscation filter automatically converting the symbol '@' 
# to the string ' <at> ' (specifically, the shell positional parameter 
# expansion "[email protected]" is changed to "$ <at>"), so don't try to use this copy: 
# http://permalink.gmane.org/gmane.comp.version-control.git/247581 

#cwd=$(git rev-parse --show-toplevel) 
git=$(git rev-parse --git-dir) 
if [ $? -ne 0 ]; then 
    exit 1 
fi 

command=$(basename $0) 
command="git ${command##git-}" 

# Print argument (and newline) to stdout or stderr 
stdout() { 
    printf %s\\n "$1" 
} 
stderr() { 
    printf %s\\n "$1" >&2 
} 

# POSIX compatible argument quoting and parameter save/restore 
# http://www.etalabs.net/sh_tricks.html 
save() { 
    local param 
    for param; do 
     printf %s\\n "$param" \ 
      | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" 
    done 
    printf %s\\n " " 
} 
# parameters=$(save "[email protected]") 
# eval "set -- ${parameters}" # to restore the original parameters. 

# Process option parameters 
parameters= 
while [ $# -gt 0 ]; do 
    case "$1" in 
     (--   ) shift; break;; 
     (-d|--delete) delete=1; shift;; 
     (-h|--help ) help=1; shift;; 
     (-*   ) { 
      stdout "Invalid option: $1" 
      shorthelp=1 
      shift 
     };; 
     (*) { # non-option parameter 
      parameters="${parameters}$(save "$1")" 
      shift 
     };; 
    esac 
done 

# Process non-option parameters 
eval "set -- ${parameters}" 
symref=$1 
branch=$2 

if [ -z "${symref}" ]; then 
    help=1 
fi 

# n.b. Calling "git branch-alias --help" causes git to look for 
# a man page for "git-branch-alias", so we shouldn't advertise 
# the long option (although we support it if the script is called 
# by its real name, rather than via git). 
if [ -n "${shorthelp}" ]; then 
    cat <<EOF 

For help, use: ${command} -h 

EOF 
    exit 0 
fi 

if [ -n "${help}" ]; then 
    cat <<EOF 
Usage: 
${command} <alias> [<branch>] 
${command} (-d | --delete) <alias> 

Creates a symbolic reference <alias> referring to <branch>. 
<branch> defaults to the current checked-out branch. 

This symbolic reference acts as an alias for <branch>, and can be 
used in its place. More specifically, it WILL be dereferenced to 
its target in nearly all situations, so for any given command you 
should treat every usage of <alias> as if it were actually <branch>. 

To safely delete a branch alias, always use: 
${command} -d <alias> 

WARNING: These symbolic references appear in your branch list as: 
<alias> -> <branch> 
and so you might be tempted to try to delete them like a branch: 
git branch -d <alias> 

However this can cause problems. In git versions prior to 1.8.0.1 
<alias> will be dereferenced and you will instead delete the 
branch it refers to (git will allow this even if you currently 
have that branch checked out), and the symbolic reference will 
still remain (referencing a branch which is no longer available). 

In later versions of git the <alias> will be deleted rather than 
the branch; however git will still not check to see whether you 
currently have <alias> checked out, and will not prevent you 
from deleting it in that situation. This will leave your HEAD ref 
in an invalid state. Using ${command} -d <alias> resolves 
this situation by first switching HEAD to <alias>'s target branch 
if HEAD was currently set to <alias>. 

EOF 
    exit 0 
fi 

# Use the current branch by default. 
if [ -z "${branch}" ]; then 
    branch=$(git symbolic-ref -q HEAD) 
    if [ $? -ne 0 ]; then 
     stderr "Could not establish current HEAD." 
     exit 1 
    fi 
fi 

# We expect plain branch names, but also accept the fully-qualified 
# (refs/heads/NAME) paths needed by git symbolic-ref; so strip that 
# refs/heads/ prefix if it is specified. 
branch=${branch##refs/heads/} 
symref=${symref##refs/heads/} 

# Deleting a symref. 
if [ -n "${delete}" ]; then 
    if [ ! -f "${git}/refs/heads/${symref}" ]; then 
     stderr "Symbolic reference refs/heads/${symref} does not exist." 
     exit 1 
    fi 

    # Verify that it IS a symbolic reference 
    if ! git symbolic-ref "refs/heads/${symref}" >/dev/null; then 
     stderr "Error validating refs/heads/${symref} as symbolic reference." 
     exit 1 
    fi 

    # If we currently have <symref> checked out, deleting it is bad 
    # (as HEAD would no longer be a valid reference). I believe we do 
    # need to inspect the file here, as attempting to read the HEAD 
    # reference via git dereferences it to its target branch, and thus 
    # we are unable to distinguish between the branch and the symref. 
    if grep -q "^ref: refs/heads/${symref}\$" "${git}/HEAD"; then 
     stdout "Cannot delete the currently checked out symbolic reference." 
     branch=$(git symbolic-ref -q HEAD) 
     if [ $? -ne 0 ]; then 
      stderr "Could not establish current HEAD." 
      exit 1 
     fi 
     stdout "Switching HEAD to target branch ${branch}" 
     # By using git symbolic-ref HEAD to find the target ref 
     # and setting HEAD to that target, nothing really changes, 
     # but we can now delete the reference safely. 
     if ! git symbolic-ref HEAD "${branch}"; then 
      stderr "Error updating HEAD from ${symref} to ${branch}" 
      stderr "Aborting." 
      exit 1 
     fi 
    fi 

    # Delete the reference. 
    # git 1.8.1+ provides: git symbolic-ref --delete <symref> 
    # but older versions do not include that option, so we use 
    # the backwards-compatible command. 
    stdout "Deleting symbolic reference refs/heads/${symref}" 
    git update-ref -d --no-deref "refs/heads/${symref}" 
    exit $? 
fi 

# Creating a new symbolic reference. 

# Error checking. git symbolic-ref doesn't really do any, and will 
# happily mess up your branches; particularly if you get the arguments 
# the wrong way around (treating it like ln -s is a really bad idea). 
if [ ! -f "${git}/refs/heads/${branch}" ]; then 
    stderr "Target refs/heads/${branch} does not exist." 
    exit 1 
fi 
if [ -f "${git}/refs/heads/${symref}" ]; then 
    target=$(git symbolic-ref "refs/heads/${symref}") 
    if [ $? -eq 0 ]; then 
     stderr "Symbolic reference refs/heads/${symref} already exists:" 
     stderr " ${symref} -> ${target##refs/heads/}" 
     stderr "To remove it, use: ${command} --delete ${symref}" 
    else 
     stderr "File refs/heads/${symref} already exists" 
     stderr "(and is not a symbolic reference!)" 
    fi 
    exit 1 
fi 
if git show-ref --verify --heads --quiet "refs/heads/${symref}"; then 
    # n.b. I'm pretty sure this is unreachable, given the previous block. 
    stderr "refs/heads/${symref} is a valid reference without a file!?" 
    exit 1 
fi 

# The parameters are good. 
# Generate the reference and display the confirmed result. 
if git symbolic-ref "refs/heads/${symref}" "refs/heads/${branch}"; then 
    target=$(git symbolic-ref "refs/heads/${symref}") 
    stdout " ${symref} -> ${target##refs/heads/}" 
else 
    stderr "Failed to create branch alias." 
    exit 1 
fi 
+0

Điều này không thành công với tôi với Git 2.7.0 trên OS X trong zsh: 'Mục tiêu refs/heads/-l không tồn tại.' bất kể tôi đang sử dụng đối số nào. – iconoclast

+0

Cảm ơn bạn đã trả lời! Trong câu trả lời cho câu hỏi của bạn, * yes *, đây là thông điệp chính xác: 'Mục tiêu refs/heads/-l không tồn tại.' Tôi đã thử nghiệm dưới bash, và nó vẫn làm được. Tôi đảo ngược các lập luận, và nó vẫn làm được. Tôi đã làm 'unalias git' trong zsh, để đảm bảo không có gì can thiệp, và nó vẫn làm được. Tôi đã sử dụng con đường hoàn chỉnh để git, và nó vẫn làm được. Tôi đã sử dụng đường dẫn đầy đủ tới 'git-branch-alias' và nó vẫn làm được. – iconoclast

+0

Tôi không nghĩ rằng điều này có thể liên quan, nhưng 'đó -a git' cho thấy 2 phiên bản trên hệ thống của tôi. Tôi không nghĩ rằng thứ hai có thể được sử dụng ở tất cả, nhưng ... Tôi đã có '/ usr/local/bin/git' và'/usr/bin/git', với người đầu tiên trước đó trong PATH . Thứ hai là 2.5.4. – iconoclast

Các vấn đề liên quan