kéo / đẩy từ nhiều địa điểm từ xa


743

Tóm lại: có cách nào để có một git repo đẩy và kéo từ một danh sách các repos từ xa (chứ không phải là một "nguồn gốc" duy nhất) không?

Từ lâu: Tôi thường gặp tình huống khi tôi đang phát triển một ứng dụng trên nhiều máy tính, với các kết nối khác nhau - giả sử một máy tính xách tay khi đang di chuyển, một máy tính "A" trong khi tôi đang ở một địa điểm nhất định và một máy tính khác "B" trong khi trên một cái khác Ngoài ra, máy tính xách tay có thể có kết nối chỉ với "A" hoặc "B" và đôi khi cả hai.

Những gì tôi muốn là để git luôn "kéo" từ và "đẩy" đến tất cả các máy tính mà nó hiện có thể kết nối, vì vậy việc chuyển từ máy này sang máy khác dễ dàng hơn và tiếp tục hoạt động trơn tru.


39
Lưu ý dành cho du khách mới, tính đến 2016: Cách hiện-đúng để làm điều này, xử phạt bằng hạng nhất gittính năng, được bao gồm trong malvineous 's câu trả lời dưới đây . Câu trả lời được chấp nhận là không chính xác.
ELLIOTTCABLE

@Zorzella: Bạn có thể cập nhật câu trả lời được chấp nhận về điều này không, nó hơi khó hiểu theo cách hiện tại.
ntninja

Câu trả lời:


503

Bạn có thể cấu hình nhiều kho lưu trữ từ xa bằng git remotelệnh:

git remote add alt alt-machine:/path/to/repo

Để tìm nạp từ tất cả các điều khiển từ xa được cấu hình và cập nhật các nhánh theo dõi, nhưng không hợp nhất vào HEAD, hãy làm:

git remote update

Nếu hiện tại nó không được kết nối với một trong các điều khiển từ xa, nó sẽ mất thời gian hoặc đưa ra lỗi và chuyển sang phần tiếp theo. Bạn sẽ phải hợp nhất thủ công từ kho lưu trữ được tìm nạp hoặc cherry-picktùy thuộc vào cách bạn muốn tổ chức thu thập thay đổi.

Để tìm nạp nhánh chính từ alt và kéo nó vào đầu hiện tại của bạn, hãy làm:

git pull alt master

Vì vậy, trên thực tế git pullgần như là tốc ký cho git pull origin HEAD(thực tế nó tìm trong tệp cấu hình để xác định điều này, nhưng bạn có ý tưởng).

Để đẩy các bản cập nhật, bạn phải làm điều đó với mỗi repo bằng tay.
Tôi nghĩ rằng một sự thúc đẩy được thiết kế với luồng công việc của kho lưu trữ trung tâm.


Vì vậy, những gì bạn đang nói là "git remote add foo ssh: //foo.bar/baz" tạo ra một dạng tốc ký, nhưng tôi vẫn cần lặp lại chúng bằng "git pull", hoặc lặp qua chúng bằng "git hợp nhất "(cú pháp ở đây là gì, sau khi" git remove update "?) Tên viết tắt này cũng hoạt động cho" git đẩy "? Tức là tôi không thể "git đẩy foo" vv (vòng lặp)? Cảm ơn
Zorzella

8
"Git pull" về cơ bản là "git fetch" theo sau là "git merge". "git cập nhật từ xa" chỉ thực hiện một loạt các cuộc gọi "git fetch" cho bạn. Vì vậy, những gì còn lại là để làm bit "git merge". Bạn có thể nói "git merge origin / master" và nó sẽ hợp nhất phiên bản chính của bản gốc vào ĐẦU hiện tại của bạn. "git pull origin master" cũng làm điều tương tự, mặc dù nó sẽ thực hiện tìm nạp trước (và nếu bạn đã thực hiện cập nhật từ xa git, điều đó sẽ không có gì để tìm nạp thêm, vì vậy nó không cần thiết). Có, bạn có thể nói "git push foo" và nó sẽ đẩy tất cả các nhánh phù hợp đến điều khiển từ xa được gọi là "foo".
araqnid

IIUC bạn không thể đẩy vào một kho lưu trữ đang hoạt động (sau tất cả những gì bạn có thể đang đẩy những thay đổi không tương thích / chưa được kiểm tra / không mong muốn). Chúng tôi phải đẩy vào kho lưu trữ trần và chỉ nhận được cập nhật khi chúng tôi kéo. Vì vậy, giải pháp đòi hỏi một kho lưu trữ làm việc và trần trên mỗi máy?
joeytwiddle

2
Rõ ràng bạn cũng có thể có một lần đẩy cho một số repos, hãy kiểm tra câu trả lời này để biết thêm chi tiết stackoverflow.com/questions/14290113/ chủ
manei_cc

797

Làm điều này bằng tay không còn cần thiết , với các phiên bản hiện đại của git! Xem giải pháp của Malvineous , bên dưới.

Tái sản xuất tại đây:

git remote set-url origin --push --add <a remote>
git remote set-url origin --push --add <another remote>

Câu trả lời gốc:

Đây là thứ tôi đã sử dụng trong một thời gian dài mà không có hậu quả xấu và được đề xuất bởi Linus Torvalds trong danh sách gửi thư git .

Giải pháp của araqnid là giải pháp phù hợp để đưa mã vào kho lưu trữ của bạn, nhưng khi bạn, như tôi, có nhiều luồng ngược có thẩm quyền tương đương (Tôi giữ một số dự án quan trọng hơn của tôi được sao chép cho cả thượng nguồn riêng, GitHub và Codaset), nó có thể là một nỗi đau để thúc đẩy thay đổi cho mỗi người, mỗi ngày.

Câu chuyện dài ngắn, git remote addtất cả các điều khiển từ xa của bạn riêng lẻ và sau đó git config -evà thêm một điều khiển từ xa. Giả sử bạn có kho lưu trữ này config:

[remote "GitHub"]
    url = git@github.com:elliottcable/Paws.o.git
    fetch = +refs/heads/*:refs/remotes/GitHub/*
[branch "Master"]
    remote = GitHub
    merge = refs/heads/Master
[remote "Codaset"]
    url = git@codaset.com:elliottcable/paws-o.git
    fetch = +refs/heads/*:refs/remotes/Codaset/*
[remote "Paws"]
    url = git@github.com:Paws/Paws.o.git
    fetch = +refs/heads/*:refs/remotes/Paws/*

Để tạo ra một điều khiển từ xa được hợp nhất "Paws""Codaset", tôi có thể thêm vào sau đây sau tất cả những điều sau:

[remote "Origin"]
    url = git@github.com:Paws/Paws.o.git
    url = git@codaset.com:elliottcable/paws-o.git

Khi tôi đã làm điều này, khi tôi git push Origin Master, nó sẽ đẩy đến cả hai Paws/MasterCodaset/Mastertuần tự, làm cho cuộc sống dễ dàng hơn một chút.


104
git config -emở .git/configtập tin trong trình soạn thảo ưa thích của bạn.
Richard

3
Chỉ trong trường hợp. Xác nhận rằng có một điều khiển từ xa với 2 url vẫn thực hiện công việc vào ngày 1.7.12.4. Cảm ơn.
foobar

26
Tôi đặt tên cho "nguồn gốc" từ xa "tất cả" để cung cấp cho nó ngữ nghĩa sạch hơn một chút
ErichBSchulz

1
@JamesWomack xem câu trả lời của @ Malvineous, bên dưới. Bây giờ, nó đúng hơn, vì gitdòng lệnh hỗ trợ điều này, với git remote set-url ... --add.
ELLIOTTCABLE

1
Theo [branch "Master"]thiết lập remote = Origingit pullsẽ sử dụng cả hai điều khiển từ xa.
Bengt

264

Kể từ git 1.8 (tháng 10 năm 2012), bạn có thể thực hiện việc này từ dòng lệnh:

git remote set-url origin --push --add user1@repo1
git remote set-url origin --push --add user2@repo2
git remote -v

Sau đó git pushsẽ đẩy sang user1 @ repo1, sau đó đẩy sang user2 @ repo2.


19
Tôi khuyên bạn nên chống lại giải pháp này. Chúng tôi đã sử dụng nó trong công ty của chúng tôi và gặp rắc rối nghiêm trọng với các lỗi bị lỗi tại một kho lưu trữ, nhưng không phải ở kho khác. Thay đổi sau đó chỉ có mặt trong một kho lưu trữ.
Michael Schmeißer

4
@ MichaelSchmeißer: Có lẽ bạn có thể thấy các thông báo lỗi khi đẩy mặc dù, khắc phục sự cố, sau đó đẩy lại để đưa mọi thứ trở lại trạng thái sạch?
Malvineous

7
Vấn đề là việc sửa lỗi đẩy bị từ chối liên quan đến việc thay đổi các cam kết đã được đẩy sang repo khác. Vì vậy, nếu ai đó đã làm việc dựa trên những cam kết đó vào thời điểm họ cố định, mọi thứ trở nên thực sự khó chịu, đó là trường hợp trong văn phòng của chúng tôi.
Michael Schmeißer

9
À vâng, điều đó có thể trở nên khó khăn. Tuy nhiên với tôi có vẻ như các móc cần phải được thiết kế lại. Một lần đẩy thất bại không phá vỡ git bình thường, do đó, giới thiệu một điểm thất bại mới (điều này cũng ngăn bạn sử dụng tính năng git tiện lợi) có lẽ không phải là giải pháp tốt nhất. Tất nhiên tôi nói điều này mà không biết yêu cầu của bạn là gì ...
Malvineous

3
Không. Kể từ khi viết câu hỏi của tôi, tôi đã đọc các bài đăng trên web khác và sau đó thử nghiệm điều này. Từ việc đọc các bài đăng khác, tôi đã có sự nghi ngờ rằng chỉ có dòng đầu tiên được sử dụng. Tôi vừa mới thử nghiệm điều này: thực sự, chỉ có URL từ dòng đầu tiên được kiểm tra bởi git fetch. (Vì điều này, tôi không hiểu mục đích của việc không git remote set-url --addthể là gì --push.)
imz - Ivan Zakharyaschev

34

Tôi đã thêm các bí danh này vào ~ / .bashrc:

alias pushall='for i in `git remote`; do git push $i; done;'
alias pullall='for i in `git remote`; do git pull $i; done;'

6
Điều này thật tuyệt! git config alias.pushall '!for i in ; do git push $i; done;'
Cuối

Tôi nghĩ rằng tôi thích giải pháp bí danh để tạo ra một điều khiển từ xa mới. Xem thêm stackoverflow.com/questions/41372919/
Mạnh

1
Tinh chỉnh nhỏ được đề xuất:alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
Scott C Wilson

25

Bạn có thể thêm điều khiển từ xa bằng:

git remote add a urla
git remote add b urlb

Sau đó, để cập nhật tất cả các repos làm:

git remote update

15

Dưới đây là ví dụ của tôi với tập lệnh bash bên trong .gitconfigphần bí danh

[alias]
        pushall = "!f(){ for i in `git remote`; do git push $i; done; };f"

7

Tôi đã thêm hai đẩy riêng biệt vào "nguồn gốc" từ xa trong tệp .fit congfig. Khi tôi chạy git push origin "branchName"thì nó sẽ chạy qua và đẩy đến từng url. Không chắc chắn liệu có cách nào dễ dàng hơn để thực hiện việc này hay không nhưng cách này hiệu quả đối với bản thân tôi để đẩy mã nguồn Github và đẩy mã nguồn My.visualStudio cùng một lúc.

[remote "origin"]
  url = "Main Repo URL"
  fetch = +refs/heads/*:refs/remotes/origin/*
  pushurl = "repo1 URL"
  pushurl = "reop2 URl"

4

Tôi lấy tự do để mở rộng câu trả lời từ non-urbiz; chỉ cần thêm nó vào ~ / .bashrc:

git-pullall () { for RMT in $(git remote); do git pull -v $RMT $1; done; }    
alias git-pullall=git-pullall

git-pushall () { for RMT in $(git remote); do git push -v $RMT $1; done; }
alias git-pushall=git-pushall

Sử dụng:

git-pullall master

git-pushall master ## or
git-pushall

Nếu bạn không cung cấp bất kỳ đối số nhánh nào cho git-pullall thì việc kéo từ điều khiển từ xa không mặc định sẽ thất bại; để lại hành vi này, vì nó tương tự như git.


3

Bạn sẽ cần một kịch bản để lặp qua chúng. Git không cung cấp một "đẩy tất cả." Về mặt lý thuyết bạn có thể thực hiện một cú đẩy trong nhiều luồng, nhưng một phương thức riêng không có sẵn.

Fetch thậm chí còn phức tạp hơn, và tôi khuyên bạn nên làm điều đó một cách tuyến tính.

Tôi nghĩ rằng câu trả lời tốt nhất của bạn là có một lần máy mà mọi người thực hiện đẩy / kéo, nếu điều đó hoàn toàn có thể.


2
Vấn đề là, như tôi đã mô tả, không có hộp trung tâm luôn có sẵn. Nếu tôi phải viết một kịch bản bash lặp, thì cũng vậy, nhưng thật buồn cười khi một VC phân tán sẽ không giúp tôi nhiều hơn ở đây ...
Zorzella

2
Được phân phối, nó giả định rằng không phải ai cũng có sẵn, hoặc muốn được đẩy đến. Nó cũng liên quan đến các kho lưu trữ khác nhau ở các trạng thái khác nhau và giả định rằng những người khác đang làm việc trên chúng đồng thời. Thứ tự bạn đẩy và kéo từ một tập hợp các kho lưu trữ ảnh hưởng đến trạng thái của các kho khác nhau và bạn phải thực hiện nhiều lần để tất cả chúng được đồng bộ hóa thực sự. Đây là lý do tại sao không có "kéo / đẩy tất cả". Sau đó, có xung đột ...;)
Jeff Ferland

3

Để cập nhật các điều khiển từ xa (ví dụ như pulltrường hợp), mọi thứ đã trở nên dễ dàng hơn.

Tuyên bố của Linus

Đáng buồn thay, thậm chí không có cách nào để giả mạo điều này với bí danh git.

trong mục được tham chiếu tại danh sách gửi thư Git trong câu trả lời của elliottcable không còn đúng nữa.

git fetchđã học được --alltham số ở đâu đó trong quá khứ cho phép tìm nạp tất cả các điều khiển từ xa trong một lần.

Nếu không phải tất cả được yêu cầu, người ta có thể sử dụng công --multipletắc để chỉ định nhiều điều khiển từ xa hoặc một nhóm.


3

Tôi muốn làm việc trong VSO / TFS, sau đó đẩy công khai lên GitHub khi sẵn sàng. Repo ban đầu được tạo trong VSO riêng. Khi đến lúc thêm vào GitHub tôi đã làm:

git remote add mygithubrepo https://github.com/jhealy/kinect2.git
git push -f mygithubrepo master

Làm việc như một nhà vô địch ...

Để kiểm tra độ tỉnh táo, hãy phát hành "git remote -v" để liệt kê các kho lưu trữ liên quan đến một dự án.

C:\dev\kinect\vso-repo-k2work\FaceNSkinWPF>git remote -v
githubrepo      https://github.com/jhealy/kinect2.git (fetch)
githubrepo      https://github.com/jhealy/kinect2.git (push)
origin  https://devfish.visualstudio.com/DefaultCollection/_git/Kinect2Work (fetch)
origin  https://devfish.visualstudio.com/DefaultCollection/_git/Kinect2Work (push)

Cách đơn giản, làm việc cho tôi ... Hy vọng điều này sẽ giúp được ai đó.


4
Chạy git push -fmà không có lý do, ví dụ như thất bại git pushhoặc biết chính xác những gì mình đang làm, là một ý tưởng tồi có thể gây hại. Điều này cũng không trả lời câu hỏi, nhưng làm thế nào để thêm một điều khiển từ xa thứ hai.
Karl Richter

2

thêm một bí danh cho gitconfig toàn cầu (/home/user/.gitconfig) bằng lệnh bên dưới.

git config --global alias.pushall '!f(){ for var in $(git remote show); do echo "pushing to $var"; git push $var; done; }; f'

Khi bạn cam kết mã, chúng tôi nói

đẩy git

để đẩy về nguồn gốc theo mặc định. Sau bí danh trên, chúng ta có thể nói

git đẩy

và mã sẽ được cập nhật cho tất cả các điều khiển từ xa bao gồm cả điều khiển từ xa.


1

Việc thêm allđiều khiển sẽ hơi tẻ nhạt khi bạn phải thiết lập trên mỗi máy mà bạn sử dụng.

Ngoài ra, các bí danhbash và cung cấp tất cả giả định rằng bạn có sẽ đẩy đến tất cả các điều khiển từ xa. (Ví dụ: Tôi có một ngã ba mà tôi duy trì trên GitHub và GitLab. Tôi có thêm điều khiển từ xa ngược dòng , nhưng tôi không được phép đẩy nó.)git sshag

Đây là một git bí danh chỉ đẩy để từ xa với một URL đẩy bao gồm @.

psall    = "!f() { \
    for R in $(git remote -v | awk '/@.*push/ { print $1 }'); do \
    git push $R $1; \
    done \
    }; f"

-3

Thêm điều khiển mới

git remote add upstream https://github.com/example-org/example-repo.git

git remote -vv

Lấy mẫu nhiều vị trí

git fetch --all

Đẩy đến vị trí

git push -u upstream/dev
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.