2010-01-21 6 views
40

Tôi mới dùng shell scripting và không thể tìm ra điều này. Nếu bạn không quen thuộc, chi nhánh lệnh git trả về một cái gì đó nhưLàm thế nào để lấy tên của nhánh git hiện tại thành một biến trong một kịch bản lệnh shell?

* develop 
    master 

, trong đó dấu hoa thị đánh dấu nhánh hiện đã được kiểm tra. Khi tôi chạy sau trong terminal:

git branch | grep "*" 

tôi nhận được:

* develop 

như mong đợi.

Tuy nhiên, khi tôi chạy

test=$(git branch | grep "*") 

hoặc

test=`git branch | grep "*"` 

Và sau đó

echo $test 

, kết quả là chỉ là một danh sách các tập tin trong thư mục. Làm thế nào để chúng ta làm cho giá trị của test = "* phát triển"?

Sau đó, bước tiếp theo (khi chúng tôi nhận được "* phát triển" thành một biến được gọi là thử nghiệm), là lấy chuỗi con. Điều đó có đúng không?

currentBranch=${test:2} 

Tôi đã chơi xung quanh với chức năng chuỗi con đó và tôi gặp lỗi "thay thế xấu" rất nhiều và không biết tại sao.

+0

gì nếu bạn sử dụng dấu nháy đơn xung quanh dấu : ''*'' thay vì '" * "' –

+0

@glenn không phải là nơi mà sự giãn nở xảy ra, nó ở trong tiếng vọng, như marco đã được biên soạn. – wich

+0

Hãy thử [bài đăng trên blog này] (http://railstips.org/blog/archives/2009/02/02/bedazzle-your-bash-prompt-with-git-info/). –

Trả lời

58

Các * được mở rộng, những gì bạn có thể làm là sử dụng sed thay vì grep và lấy tên của chi nhánh ngay lập tức:

Và một phiên bản sử dụng git symbolic-ref, theo đề nghị của Noufal Ibrahim

branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,') 

để xây dựng trên việc mở rộng, (như marco đã làm,) việc mở rộng sẽ xảy ra trong tiếng vang, khi bạn làm echo $test với thử nghiệm $ chứa "* chủ" thì * được mở rộng theo các quy tắc mở rộng bình thường. Để ngăn chặn điều này sẽ phải trích dẫn biến, như được hiển thị bởi marco: echo "$test". Ngoài ra, nếu bạn loại bỏ dấu sao trước khi bạn lặp lại, tất cả sẽ ổn, ví dụ: echo ${test:2} sẽ chỉ phản hồi "chính". Ngoài ra, bạn có thể gán cho nó một lần nữa như bạn đã đề xuất:

branch=${test:2} 
echo $branch 

Điều này sẽ lặp lại "chính", giống như bạn muốn.

+2

Nó sẽ là lịch sự của bạn để đề cập đến câu trả lời của tôi nếu bạn sử dụng các yếu tố từ nó để cập nhật của bạn. –

+0

Tất nhiên, lời xin lỗi của tôi, tôi đã cập nhật nhanh chóng trước khi rời đi, đã bỏ lỡ ghi nhận tác giả. – wich

+1

ok, vì vậy tôi đã thử cả hai phương pháp, và tôi phải nói rằng 'symbolic-ref' sẽ không luôn hoạt động. ví dụ: nếu bạn kiểm tra một số commit cũ, nó sẽ ném lỗi, trong khi lệnh 'sed' cho cái gì đó như' (HEAD tách ra ở 1qw23er) ' – zhirzh

26

Tôi sẽ sử dụng lệnh git-symbolic-ref trong lõi git. Nếu bạn nói git-symbolic-ref HEAD, bạn sẽ nhận được tên của chi nhánh hiện tại.

+0

+1 cho 'git-symbolic-ref';) – VonC

+11

Trong phiên bản mới hơn của git, bạn sẽ phải sử dụng git symbolic-ref HEAD để thay thế. –

1

vô hiệu hóa việc mở rộng subshell glob,

test=$(set -f; git branch) 
+0

đó không phải là nơi mở rộng xảy ra, đó là trong tiếng vọng, như marco đã được xây dựng trên. – wich

7

vấn đề này dựa trên:

echo $test 

Trong thực tế, kiểm tra biến chứa một ký tự đại diện được mở rộng bằng vỏ.Để tránh điều đó chỉ bảo vệ $ thử nghiệm với dấu ngoặc kép:

echo "$test" 
+1

+1 để có câu trả lời hay nhất. –

46

Mở rộng về câu trả lời Noufal Ibrahim, sử dụng --short cờ với git-symbolic-ref, không cần phải phiền phức với sed.

Tôi đã sử dụng một cái gì đó như thế này trong móc và nó hoạt động tốt:

#!/bin/bash 

branch=$(git symbolic-ref --short HEAD) 

echo 
echo "**** Running post-commit hook from branch $branch" 
echo 

Đó quả đầu ra "**** Chạy sau cam kết nối từ tổng thể chi nhánh"

Lưu ý rằng chỉ git-symbolic-ref hoạt động nếu bạn đang ở trong kho lưu trữ. May mắn là .git/HEAD, như một phần còn lại từ những ngày đầu của Git, chứa đựng cùng một biểu tượng. Nếu bạn muốn nhận được các chi nhánh hoạt động của một vài kho git, mà không đi qua các thư mục, bạn có thể sử dụng một bash một lót như thế này:

for repo in */.git; do branch=$(cat $repo/HEAD); echo ${repo%/.git} : ${branch##*/}; done 

Những kết quả đầu ra một cái gì đó như:

repo1 : master 
repo2 : dev 
repo3 : issue12 

Nếu bạn muốn để đi xa hơn, toàn bộ ref chứa trong .git/HEAD cũng là một đường dẫn tương đối đến một tệp chứa hàm băm SHA-1 của cam kết cuối cùng của nhánh.

+3

'alias currentgitbranch = 'git symbolic-ref --short HEAD'' – Pat

+1

Đây là câu trả lời hay nhất, sử dụng' --short' chỉ cho bạn chuỗi bạn đang tìm kiếm. Cảm ơn! – 0atman

9

tôi sử dụng này git describe --contains --all HEAD trong kịch bản helper git tôi

dụ:

#!/bin/bash 
branchname=$(git describe --contains --all HEAD) 
git pull --rebase origin $branchname 

Tôi có rằng trong một tập tin gọi là gpull trong ~/scripts

+0

'git description --contains --all HEAD' không cho tôi nhánh hiện tại được đánh dấu bởi một ngôi sao có' git branch'. – hakre

+0

điều này hữu ích trong kịch bản xây dựng jenkins, cảm ơn – nemesisdesign