Làm cách nào tôi có thể đẩy một cam kết cụ thể đến một điều khiển từ xa chứ không phải các cam kết trước đó?


Câu trả lời:


1087

Để đẩy lên thông qua một cam kết nhất định, bạn có thể viết:

git push <remotename> <commit SHA>:<remotebranchname>

cung cấp <remotebranchname>đã tồn tại trên điều khiển từ xa. (Nếu không, bạn có thể sử dụng git push <remotename> <commit SHA>:refs/heads/<remotebranchname>để tự động tạo nó.)

Nếu bạn muốn đẩy một cam kết mà không đẩy các cam kết trước đó, trước tiên bạn nên sử dụng git rebase -iđể đặt hàng lại các cam kết.


66
git push <remotename> <commit SHA>:<remotebranchname>làm. mẹo là kết hợp nó với git rebase -iđể di chuyển cam kết bạn muốn làm cam kết đầu tiên và chỉ định cam kết đó
dminer

29
một mẹo hay khác là đảm bảo bạn sao chép SHA của cam kết bạn muốn đẩy sau khi thực hiện rebase đó -i, chứ không phải trước đó, như tôi vừa làm :)
estan

33
Hãy nhớ rằng điều này không thành công nếu nhánh từ xa chưa tồn tại. Tạo chi nhánh có thể được thực hiện với git push <remotename> <commit SHA>:refs/heads/<new remote branch name>. Sau đó, đẩy như câu trả lời mô tả.
Wes Oldenbeuving

32
Ví dụ, để đẩy mọi thứ trừ cam kết cuối cùng với một số tên tiêu chuẩn git push origin HEAD~1:master.
tiếng ồn vô nghĩa

3
Cũng lưu ý rằng, nếu bạn đã đẩy một SHA sau này đến nhánh từ xa đó, thì bạn sẽ cần phải đẩy cái này. Sử dụng -fcờ.
Ian Vaughan

79

Các câu trả lời khác là thiếu trên các mô tả sắp xếp lại.

git push <remotename> <commit SHA>:<remotebranchname>

sẽ đưa ra một cam kết duy nhất, nhưng cam kết đó phải là OLDEST của cam kết cục bộ, không bị đẩy, không bị nhầm lẫn với cam kết hàng đầu, đầu tiên hoặc mẹo, đó là tất cả các mô tả mơ hồ theo quan điểm của tôi. Cam kết cần đến các cam kết cũ nhất của bạn, tức là xa nhất từ ​​các cam kết gần đây nhất của bạn. Nếu đó không phải là cam kết cũ nhất thì tất cả các cam kết từ SHA cũ nhất, cục bộ, không đẩy của bạn đến SHA được chỉ định sẽ được đẩy. Để sắp xếp lại các cam kết sử dụng:

git rebase -i HEAD~xxx

Sau khi sắp xếp lại cam kết, bạn có thể đẩy nó vào kho lưu trữ từ xa một cách an toàn.

Để tóm tắt, tôi đã sử dụng

git rebase -i HEAD~<number of commits to SHA>
git push origin <post-rebase SHA>:master

để đẩy một cam kết duy nhất đến chi nhánh chủ từ xa của tôi.

Người giới thiệu:

  1. http://blog.dennisrobinson.name/push-only-one-commit-with-git/
  2. http://blog.dennisrobinson.name/reorder-commits-with-git/

Xem thêm:

  1. git: Cam kết trùng lặp sau khi Rebase cục bộ được theo dõi bởi Pull
  2. git: Đẩy các cam kết đơn lẻ, sắp xếp lại với rebase, các cam kết trùng lặp

3
Một số nguồn gốc có thể không cho phép điều này, dường như. Ví dụ với GitLab tôi thấy 'Bạn không được phép buộc mã đẩy vào một nhánh được bảo vệ trong dự án này.'. Đó là một chút kỳ lạ vì tôi đã không nghĩ rằng tôi đã ép buộc bất cứ điều gì, chỉ làm một động tác đẩy bình thường. Bất cứ ý tưởng làm thế nào để làm điều đó mà không 'buộc'?
Ed Avis

1
@Ed Shoudl không cần phải đẩy. Âm thanh như bạn có một vấn đề với thiết lập git cụ thể của bạn. Có lẽ bạn đã vượt qua các cam kết từ xa? Tôi không biết chi nhánh được bảo vệ là gì, nghe có vẻ như là một vấn đề cho phép.
Samuel

1
Samuel - điều đó sẽ có ý nghĩa, nhưng git rebase - tôi chỉ cho bạn thấy các cam kết cục bộ muộn hơn so với ĐẦU từ xa, vì vậy tôi không biết làm thế nào tôi có thể làm điều đó.
Ed Avis

1
Samuel - thực sự bây giờ tôi có thể thực hiện các động tác đẩy một phần vì vậy tôi không biết điều gì đã xảy ra nhưng chắc chắn đã cố gắng đẩy một cam kết không xuất phát từ ĐẦU từ xa bằng cách này hay cách khác.
Ed Avis

1
@Ed Bạn đã nói "git rebase -i chỉ hiển thị cho bạn các cam kết cục bộ muộn hơn so với ĐẦU từ xa", tôi không nghĩ điều này là đúng. Tôi đã thử nghiệm và có thể nổi loạn qua ĐẦU từ xa.
Samuel

25

Tôi đề nghị sử dụng git rebase -i; di chuyển các cam kết bạn muốn đẩy lên đầu các cam kết bạn đã thực hiện. Sau đó sử dụng git logđể lấy SHA của cam kết bị từ chối, kiểm tra và đẩy nó. Cuộc nổi loạn sẽ đảm bảo rằng tất cả các cam kết khác của bạn bây giờ là con của người bạn đã đẩy, vì vậy các lần đẩy trong tương lai cũng sẽ hoạt động tốt.


3
Có lẽ bạn có thể đưa ra một ví dụ hoàn thành di chuyển đặc biệt. lại git logbước?
Drux 16/12/13

4
Giả sử bạn có 3 cam kết tương đối độc lập với các thông báo "A", "B", "C" được cam kết theo thứ tự đó và bạn muốn đẩy "B". 'git rebase -i' sẽ giúp bạn và biên tập viên liệt kê cả ba; di chuyển B lên và lưu / thoát. 'git log --pretty = oneline -n3' sẽ liệt kê B, A, C với các giá trị băm trước mỗi tin nhắn, với B bây giờ là cuối cùng. 'kiểm tra git -b temp $ hash_of_B; git đẩy 'nên đẩy B vào thời điểm đó. Sau đó, bạn có thể muốn 'git checkout -b master; git chi nhánh -d temp 'để quay lại trạng thái trước đó, giả sử bạn đang ở chi nhánh chính địa phương; thay thế như áp dụng.
Walter Mundt

1
+1 Bạn đã bao giờ gặp phải "cơn thịnh nộ của các vị thần git" sau khi rebase-đẩy-rebase chưa? (Có thể tình cờ có thể xảy ra do tai nạn, phải không?)
Drux 17/12/13

2
Nếu bạn đọc kỹ câu trả lời của tôi, bạn sẽ thấy rằng việc đẩy chỉ xảy ra sau khi rebase và cam kết bị từ chối chỉ được di chuyển lên trên các cam kết khác chưa được đẩy. Khi một cam kết được đẩy, nó thường được coi là thiết lập trong đá; để nó một mình trong cuộc nổi loạn trong tương lai. Kỹ thuật này chỉ để bạn có thể sắp xếp nhiều thay đổi cục bộ thành một thứ tự tốt trước khi đẩy chúng. Nếu bạn đã thiết lập theo dõi một cách chính xác, 'git rebase -i' không có đối số nào khác sẽ mặc định không hiển thị bạn đã thực hiện các cam kết, vì vậy sẽ an toàn hơn khi gặp tai nạn so với một số phương pháp khác.
Walter Mundt

21

Cherry-pick hoạt động tốt nhất so với tất cả các phương pháp khác trong khi đẩy một cam kết cụ thể.

Cách để làm điều đó là:

Tạo một chi nhánh mới -

git branch <new-branch>

Cập nhật chi nhánh mới của bạn với chi nhánh gốc của bạn -

git fetch

git rebase

Những hành động này sẽ đảm bảo rằng bạn chính xác có cùng nội dung với nguồn gốc của bạn.

Cherry-pick sha idmà bạn muốn làm đẩy -

git cherry-pick <sha id of the commit>

Bạn có thể có được sha idbằng cách chạy

git log

Đẩy nó về nguồn gốc của bạn -

git push

Chạy gitkđể thấy rằng mọi thứ trông giống như bạn muốn.


2
Sử dụng git rebase -isẽ là giải pháp lý tưởng như đề xuất trong các giải pháp trên. Cherry pick chỉ được sử dụng khi bạn muốn nhân đôi cam kết.
Vinay Bhargav

13

Tôi tin rằng bạn sẽ phải "git hoàn nguyên" trở lại cam kết đó và sau đó đẩy nó. Hoặc bạn có thể cherry-pickcam kết vào một nhánh mới và đẩy nó tới nhánh trên kho lưu trữ từ xa. Cái gì đó như:

git branch onecommit
git checkout onecommit
git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544 # From the other branch
git push origin {branch}

9
Hoàn nguyên git là một ý tưởng tồi ở đây - nó tạo ra một mới cam
Hasen

1
@hasen: Bạn có thể chỉ cần cherry-pickcam kết bạn muốn.
Josh K

4
cả Revert và cherry-pick đều là những ý tưởng tồi. git rebase -i là bạn của bạn ở đây, xem câu trả lời từ Walter Mundt bên dưới.
Nicolas C

3
@Nicolas, tại sao cherry-pick là một ý tưởng tồi?
Antoine

3
@Antoine, thông thường bạn muốn chi nhánh của mình đồng bộ với chi nhánh mà nó theo dõi về nguồn gốc. Nếu bạn chọn, bạn đang thực hiện sao chép / dán và bạn sẽ phải đối phó với bản sao không bị đẩy vào một lúc nào đó. Nếu bạn rebase -i, bạn thực hiện "cắt và dán" và giữ chi nhánh của bạn đồng bộ với điều khiển từ xa đến nơi bạn muốn.
Nicolas C

0

Bạn cũng có thể, trong một thư mục khác:

  • git clone [kho lưu trữ của bạn]
  • Ghi đè thư mục .git trong kho lưu trữ ban đầu của bạn bằng thư mục .git của kho lưu trữ mà bạn vừa nhân bản ngay bây giờ.
  • git thêm và git cam kết ban đầu của bạn
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.