Theo dõi tất cả các chi nhánh git từ xa như các chi nhánh địa phương


175

Theo dõi một chi nhánh từ xa như một chi nhánh địa phương là đủ đơn giản.

$ git checkout --track -b ${branch_name} origin/${branch_name}

Đẩy tất cả các nhánh cục bộ lên điều khiển từ xa, tạo các nhánh từ xa mới khi cần cũng dễ dàng.

$ git push --all origin

Tôi muốn làm ngược lại. Nếu tôi có X số nhánh từ xa tại một nguồn duy nhất:

$ git branch -r 
branch1
branch2
branch3
.
.
.

Tôi có thể tạo các nhánh theo dõi cục bộ cho tất cả các nhánh từ xa mà không cần phải tự tạo từng nhánh không? Nói điều gì đó như:

$ git checkout --track -b --all origin

Tôi đã googled và RTM, nhưng đã đi lên cho đến nay.


3
Thậm chí còn có một cách đơn giản hơn để theo dõi một nhánh từ xa duy nhất là một nhánh cục bộ:git checkout --track origin/branchname
Cerran

Đây không phải là chính xác những gì bạn yêu cầu, nhưng hoạt động với tôi: nhận git hoàn thành: github.com/git/git/blob/master/contrib/completion/ Lỗi . Sau đó nhập git pull origin và nhấn tab, để có được một danh sách các chi nhánh từ xa. Sau đó tiếp tục gõ và nhấn return.
Max Heiber

Câu trả lời:


111

Sử dụng bash:

sau git 1.9.1
for i in `git branch -a | grep remote | grep -v HEAD | grep -v master`; do git branch --track ${i#remotes/origin/} $i; done

tín dụng: Val Blant, elias và Hugo

trước git 1.9.1

Lưu ý: mã sau nếu được sử dụng trong các phiên bản sau của git (> v1.9.1) gây ra

  1. (lỗi) Tất cả các nhánh được tạo để theo dõi chủ
  2. (phiền toái) Tất cả các tên chi nhánh địa phương được tạo có tiền tố origin/
for remote in `git branch -r `; do git branch --track $remote; done

Cập nhật các nhánh, giả sử không có thay đổi nào trên các nhánh theo dõi cục bộ của bạn:

for remote in `git branch -r `; do git checkout $remote ; git pull; done

Bỏ qua các cảnh báo tên gọi mơ hồ, git dường như thích chi nhánh địa phương như nó nên.


2
Cảm ơn các head-up về các cảnh báo tên. Điều đó rất hữu ích.
Paul

1
Cảm ơn Otto, tôi đã nghi ngờ rằng kịch bản sẽ là giải pháp duy nhất. Bạn đã cung cấp một cái khá đơn giản.
Janson

1
@Jason vẫn là kịch bản giải pháp duy nhất?
cregox

1
@Cawas: cho đến khi bạn phải tự tạo các nhánh theo dõi, nhưng git pullcó một --allcông tắc, sẽ tìm nạp + hợp nhất tất cả các nhánh được theo dõi.
ness101

13
Điều này không làm việc cho tôi trên Git 1.9.1. "Git chi nhánh --track <banch_name>" tạo một nhánh mới <Branch_name> theo dõi chủ chi nhánh địa phương, thay vì chi nhánh từ xa mà chúng tôi muốn. Vì vậy, kịch bản này đã tạo ra một loạt các chi nhánh địa phương tất cả chỉ đến chủ địa phương. Tôi sẽ đăng giải pháp dưới đây.
Val Blant

183

Câu trả lời được đưa ra bởi Otto là tốt, nhưng tất cả các nhánh được tạo sẽ có "nguồn gốc /" là bắt đầu của tên. Nếu bạn chỉ muốn phần cuối cùng (sau phần cuối /) là tên nhánh kết quả của bạn, hãy sử dụng phần này:

for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done

Nó cũng có lợi ích là không cung cấp cho bạn bất kỳ cảnh báo nào về các lượt giới thiệu mơ hồ.


Git sẽ không thêm "nguồn gốc" vào tên nhánh theo dõi cục bộ.
Adam Dymitruk

14
@adymitruk: Thật ra nó hoạt động chính xác như tôi đã nói với tôi trên OSX 10.6.4, sử dụng git 1.7.2.2 (ổn định mới nhất theo nhận xét này). Otto thậm chí còn đề cập đến các cảnh báo về tên gọi mơ hồ - các cảnh báo sẽ không cần tồn tại nếu "origin /" không phải là một phần của mỗi tên chi nhánh địa phương. Đây là đầu ra của 'nhánh git' sau khi chạy lệnh của Otto: [master, origin / HEAD, origin / chart, origin / master, origin / sản xuất, origin / staging]. Và lệnh của tôi: [biểu đồ, bậc thầy, sản xuất, dàn dựng].
tjmcewan

1
+ Chỉnh sửa: đã tìm thấy article.gmane.org/gmane.comp.version-control.git/112575 giải thích lý do.
Philip Oakley

8
Tôi đồng ý - đây là một giải pháp tốt hơn so với câu trả lời "được chấp nhận" hiện tại.
tobias.mcn Khoa

2
Thay vì grep -v master, làm thế nào grep -v /HEAD? Điều này dường như lọc ra nhánh mặc định, mà không cần tùy chỉnh
dashrb

22

Hầu hết các câu trả lời ở đây là quá phức tạp trong việc phân tích cú pháp đầu ra của git branch -r. Bạn có thể sử dụng forvòng lặp sau để tạo các nhánh theo dõi đối với tất cả các nhánh trên điều khiển từ xa như vậy.

Thí dụ

Nói rằng tôi có những chi nhánh từ xa.

$ git branch -r
  origin/HEAD -> origin/master
  origin/development
  origin/integration
  origin/master
  origin/production
  origin/staging

Xác nhận rằng chúng tôi không theo dõi bất cứ điều gì ngoài chủ đã có, cục bộ:

$ git branch -l    # or using just git branch
* master

Bạn có thể sử dụng một lớp lót này để tạo các nhánh theo dõi:

$ for i in $(git branch -r | grep -vE "HEAD|master"); do 
    git branch --track ${i#*/} $i; done
Branch development set up to track remote branch development from origin.
Branch integration set up to track remote branch integration from origin.
Branch production set up to track remote branch production from origin.
Branch staging set up to track remote branch staging from origin.

Bây giờ xác nhận:

$ git branch
  development
  integration
* master
  production
  staging

Để xóa chúng:

$ git br -D production development integration staging 
Deleted branch production (was xxxxx).
Deleted branch development (was xxxxx).
Deleted branch integration (was xxxxx).
Deleted branch staging (was xxxxx).

Nếu bạn sử dụng công -vvtắc để git branchbạn có thể xác nhận:

$ git br -vv
  development xxxxx [origin/development] commit log msg ....
  integration xxxxx [origin/integration] commit log msg ....
* master      xxxxx [origin/master] commit log msg ....
  production  xxxxx [origin/production] commit log msg ....
  staging     xxxxx [origin/staging] commit log msg ....

Phân tích vòng lặp for

Vòng lặp về cơ bản gọi lệnh git branch -r, lọc ra bất kỳ nhánh CHÍNH hoặc nhánh chính nào trong đầu ra bằng cách sử dụng grep -vE "HEAD|master". Để lấy tên của các nhánh trừ origin/chuỗi con, chúng ta sử dụng thao tác chuỗi của Bash ${var#stringtoremove}. Điều này sẽ loại bỏ chuỗi, "stringtoremove" khỏi biến $var. Trong trường hợp của chúng tôi, chúng tôi sẽ loại bỏ chuỗi origin/khỏi biến $i.

LƯU Ý: Hoặc bạn cũng có thể sử dụng git checkout --track ...để làm điều này:

$ for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); do 
    git checkout --track $i; done

Nhưng tôi không đặc biệt quan tâm đến phương pháp này, vì nó chuyển bạn giữa các chi nhánh khi nó thực hiện kiểm tra. Khi hoàn thành nó sẽ để lại cho bạn trên nhánh cuối cùng mà nó tạo ra.

Người giới thiệu


1
Hoạt động hoàn hảo với phiên bản git 2.3.2 (Apple Git-55)
AndrewD

22

Cập nhật Q1 2020: Mohsen Abasi đề xuất trong các bình luận , dựa trên câu trả lời của slm 2014 , cách thay thế đơn giản hơn:

for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); 

Và nó sử dụng $()thay vì backticks lỗi thời .

Như tôi đã đề cập đến trong một câu trả lời cũ , sử dụng git for-each-refcó thể nhanh hơn .
Và tôi sẽ sử dụng mới (Git 2.23+) git switchlệnh , thay thế bối rốigit checkout .

for i in $(git for-each-ref --format=%(refname:short) \
  --no-merged=origin/HEAD refs/remotes/origin); do \
    git switch --track $i; \
done

Bằng cách đó, không grepcần thiết.


Câu trả lời gốc (2011) cũ:

Đây là một lớp lót tôi sử dụng (trong vỏ bash, được thử nghiệm với msysgit1.7.4):

Để sao chép-dán:

remote=origin ; for brname in `git branch -r | grep $remote | grep -v master | grep -v HEAD | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream-to $remote/$brname $brname; done

Để dễ đọc hơn:

remote=origin ; // put here the name of the remote you want
for brname in `
    git branch -r | grep $remote | grep -v master | grep -v HEAD 
    | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'
`; do 
    git branch --set-upstream-to $remote/$brname $brname; 
done
  • nó sẽ chỉ chọn các nhánh ngược dòng từ xa mà bạn chỉ định trong remotebiến (nó có thể là ' origin' hoặc bất kỳ tên nào bạn đã đặt cho một trong những điều khiển từ xa của repo Git hiện tại của bạn).
  • nó sẽ trích xuất tên của nhánh: origin/a/Branch/Name => a/Branch/Namethông qua awkbiểu thức.
  • nó sẽ đặt nhánh ngược dòng thông qua --set-upstream-to(hoặc -u) , chứ không phải --track:
    Ưu điểm là, nếu nhánh đã tồn tại, nó sẽ không thất bại và nó sẽ không thay đổi nguồn gốc nhánh đó, nó sẽ chỉ cấu hình branch.xxx.(remote|merge)cài đặt.

    branch.aBranchName.remote=origin
    branch.aBranchName.merge=refs/heads/a/Branch/Name
    

Lệnh đó sẽ tạo các nhánh cục bộ cho tất cả các nhánh ngược dòng từ xa và đặt cài đặt từ xa và hợp nhất của chúng thành nhánh từ xa đó.


5
Điều này mang lại cho tôi "fatal: nhánh 'anything' không tồn tại" cho mọi nhánh chỉ tồn tại trên remote và không có nhánh cục bộ tương ứng.
Chris Dodd

Tôi nghĩ rằng nếu một tên chi nhánh chứa / ví dụ: Feature / rc-41-bckend, giải pháp này không hoạt động !!!!
Mohsen Abasi

@VonC Dựa trên câu trả lời của "slm": $ for i in $ (git Branch -r | grep -vE "HEAD | master" | sed 's / ^ [] \ + //'); kiểm tra git --track $ i; xong
Mohsen Abasi

@MohsenAasi Có vẻ tốt. Trong câu trả lời của tôi, tôi đã đề cập đến việc sử dụng --set-upstream-tothay vì --trackmặc dù.
VonC

@MohsenAbasi Tôi đã đưa câu trả lời của bạn vào câu trả lời để dễ nhìn hơn. Tôi đã thêm một cách có thể khác để liệt kê các chi nhánh từ xa và sử dụng git switchthay vì git checkout. Nhưng ý tưởng (rất tốt) của bạn vẫn còn.
VonC

14

Bạn có thể viết kịch bản đủ dễ dàng, nhưng tôi không biết khi nào nó có giá trị. Những nhánh đó sẽ nhanh chóng bị tụt lại phía sau và bạn phải cập nhật chúng mọi lúc.

Các nhánh từ xa sẽ tự động được cập nhật, do đó, dễ nhất là tạo chi nhánh cục bộ tại điểm mà bạn thực sự muốn làm việc trên nó.


2
Đó là một điểm hay. Trường hợp sử dụng chính mà tôi nghĩ đến là thiết lập môi trường dev cục bộ dựa trên kho git từ xa. Vì vậy, khi tôi thực hiện bản sao ban đầu của mình, tôi cũng muốn theo dõi tất cả các nhánh từ xa như chúng tại thời điểm đó.
Janson

1
Tiện dụng git upcập nhật tất cả các chi nhánh địa phương.
Hugo

9
for i in `git branch -a | grep remote`; do git branch --track ${i#remotes/origin/} $i; done

4
Tôi đã phải thêm một | grep -v HEADđường ống cho nó hoạt động đúng.
Elias Dornele

9

không có bất kỳ đoạn script nào (trong một thư mục trống):

$ git clone --bare repo_url .git
$ git config core.bare false
$ git checkout

sau đó, tất cả các chi nhánh từ xa sẽ được coi là địa phương.


bản gốc (bằng tiếng Nga) .


Đây là giải pháp đơn giản nhất cho đến nay và đã làm việc cho tôi trên 2.21.0.windows.1
Rotsiser Mho

7

Nếu bạn muốn sử dụng powershell và remote của bạn được gọi là origin. Sau đó, điều này hoạt động.

git fetch    
git branch -r  | %{$_ -replace "  origin/"} | %{git branch --track $_ "origin/$_"}

Điều này rất hữu ích, cuối cùng tôi đã sử dụng một biến thể nhỏ để làm cho nó hoạt động với git svn clone'd repo :git branch -r | %{$_ -replace " origin/"} | %{git checkout -b $_ "origin/$_"}
Nate

Tôi cũng đã thực hiện một biến thể nhỏ vì các chi nhánh địa phương của tôi đã tồn tại:git branch -r | %{$_ -replace " origin/"} | %{git branch -u "origin/$_" $_}
ch271828n

3
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do  git branch --track ${branch##*/} $branch; done

Sử dụng cái này và bạn sẽ không có cảnh báo như: refname 'origin / dev' là mơ hồ


3

Đây là giải pháp của tôi về lệnh BASH được giới thiệu bởi @tjmcewan:

for remote in `git branch -r | grep -v /HEAD `; do git branch --track ${remote/"origin/"/""}; done

Mục tiêu của tôi là giải quyết vấn đề rằng tất cả các nhánh được tạo sẽ có "origin /" là tên bắt đầu, bởi vì tôi đã kiểm tra rằng các biến $ remote vẫn bao gồm "origin /":

for remote in `git branch -r | grep -v /HEAD`; do echo $remote ; done

Sau khi tôi kiểm tra BASH của @tjmcewan, tôi thấy rằng tất cả các tên của các nhánh được theo dõi mà không có 'origin /' trên địa phương, tôi không biết tại sao.
Nick Tsai

1
Lệnh đầu tiên tạo ra các dấu vết theo dõi "chính". Đó không phải là thứ mà hầu hết mọi người có thể muốn.
Alexei Osipov

@AlexeiOsipov Cảm ơn!
Nick Tsai

2

Để thực hiện tương tự như câu trả lời của tjmcewan nhưng trên Windows, hãy gọi đây từ tệp bó :

for /f "delims=" %%r in ('git branch -r ^| grep -v master') do git checkout --track %%r

Hoặc điều này từ dòng lệnh :

for /f "delims=" %r in ('git branch -r ^| grep -v master') do git checkout --track %r

1

Từ git 2.23 trở đi:

for branch in `git branch -r | grep origin/`; do git switch -t -C ${branch#origin/} $branch; git pull; done

Các -Clá cờ cho git switchtạo ra hoặc reset nếu nó đã tồn tại.

tài liệu chuyển đổi git


0

Trong trường hợp bạn đã có một số chi nhánh kiểm tra và muốn

  • kiểm tra tất cả các chi nhánh còn lại từ xa
  • đảm bảo tất cả các chi nhánh địa phương theo dõi các chi nhánh từ xa

bạn có thể sử dụng tập lệnh tương thích bash- và zsh sau:

git branch -r | while read b; do if git branch | grep -q " ${b##*/}$"; then git branch --set-upstream ${b##*/} $b; else git branch --track ${b##*/} $b; fi; done

0
for rembranch in `git remote update 2>&1 > /dev/null ; git branch -r|egrep -wv "HEAD|master"`
do 
    git checkout --track -b `echo $rembranch|awk -F\/ '{print $2}'` $rembranch; 
done

Giải trình:

dòng 1: 'git Branch -r' (theo sau là 'git remote update' để cập nhật thông tin về các thay đổi cho remote) liệt kê tất cả các nhánh từ xa; 'egrep -vw' được sử dụng để loại bỏ các mục có CHÍNH và kết quả chính.

dòng 3: Theo dõi nhánh từ xa được đặt tên trong khi kiểm tra nó cục bộ. Một awk đơn giản được sử dụng để tránh 'origin /' là hậu tố cho các nhánh cục bộ.


0

Sử dụng bash, Nếu bạn muốn kiểm tra tất cả các chi nhánh:

for remote in `git branch -r`; do git checkout $(echo $remote | cut -d'/' -f 2); done

Điều quan trọng cần lưu ý là khi bạn thực hiện tìm nạp các nhánh theo dõi từ xa mới, bạn không tự động có các bản sao có thể chỉnh sửa cục bộ của chúng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.