Thay đổi thông báo cam kết git sau khi đẩy (cho rằng không có ai kéo từ xa)


982

Tôi đã thực hiện một cam kết git và đẩy sau đó. Tôi muốn thay đổi thông điệp cam kết. Nếu tôi hiểu chính xác, điều này là không nên vì ai đó có thể đã lấy từ kho lưu trữ từ xa trước khi tôi thực hiện những thay đổi như vậy. Nếu tôi không biết ai kéo thì sao?

Có cách nào để làm việc này không?


Bạn đã thử những gì? Giả sử bạn đã biết cách thay đổi thông điệp cam kết, rồi thử và đẩy, Git sẽ cho bạn biết những gì bạn cần làm để thực hiện nó.
Andrew Marshall

1
Xem câu trả lời cho câu hỏi "Làm cách nào để chỉnh sửa thông báo cam kết không chính xác trong git (Tôi đã đẩy)?" stackoverflow.com/a/456394/444639
Mike Rylander

4
Tuyên bố nó - Câu hỏi của Google về git commit Xếp hạng số 1!
Manish Shrivastava


Nếu bạn sửa đổi cam kết CHÍNH và đẩy thường (không có - lực lượng) thì đáng ngạc nhiên là nó không thất bại. Thông báo cam kết CHÍNH được cập nhật với Id cam kết đã thay đổi. Nó có nghĩa là các ID cam kết khác ngoại trừ CHÍNH vẫn còn nguyên. Tôi nhận thấy hành vi này với phiên bản git 2.8.1.
irsis

Câu trả lời:


1374

Thay đổi lịch sử

Nếu đó là cam kết gần đây nhất, bạn chỉ cần làm điều này:

git commit --amend

Thao tác này sẽ hiển thị trình chỉnh sửa với thông báo cam kết cuối cùng và cho phép bạn chỉnh sửa tin nhắn. (Bạn có thể sử dụng -mnếu bạn muốn xóa sạch tin nhắn cũ và sử dụng tin nhắn mới.)

Đẩy

Và sau đó khi bạn đẩy, làm điều này:

git push --force-with-lease <repository> <branch>

Hoặc bạn có thể sử dụng "+":

git push <repository> +<branch>

Hoặc bạn có thể sử dụng --force:

git push --force <repository> <branch>

Hãy cẩn thận khi sử dụng các lệnh này.

  • Nếu ai đó đẩy các thay đổi vào cùng một chi nhánh, có lẽ bạn muốn tránh phá hủy những thay đổi đó. Các--force-with-lease tùy chọn là an toàn nhất, bởi vì nó sẽ hủy bỏ nếu có bất kỳ thay đổi ở thượng nguồn (

  • Nếu bạn không chỉ định chi nhánh rõ ràng, Git sẽ sử dụng cài đặt đẩy mặc định. Nếu cài đặt đẩy mặc định của bạn là "khớp", thì bạn có thể hủy các thay đổi trên một số nhánh cùng một lúc.

Kéo / lấy sau đó

Bất cứ ai đã kéo bây giờ sẽ nhận được thông báo lỗi và họ sẽ cần cập nhật (giả sử họ không thực hiện bất kỳ thay đổi nào) bằng cách thực hiện một cái gì đó như thế này:

git fetch origin
git reset --hard origin/master # Loses local commits

Cẩn thận khi sử dụng reset --hard. Nếu bạn có thay đổi cho chi nhánh, những thay đổi đó sẽ bị hủy.

Một lưu ý về sửa đổi lịch sử

Dữ liệu bị hủy thực sự chỉ là thông điệp cam kết cũ, nhưng --forcekhông biết điều đó và cũng sẽ vui vẻ xóa các dữ liệu khác. Vì vậy, hãy nghĩ đến --force"Tôi muốn hủy dữ liệu và tôi biết chắc chắn dữ liệu nào đang bị hủy." Nhưng khi dữ liệu bị hủy được cam kết, bạn thường có thể khôi phục các xác nhận cũ từ reflog, dữ liệu thực sự mồ côi thay vì bị hủy (mặc dù các cam kết mồ côi bị xóa theo định kỳ).

Nếu bạn không nghĩ mình đang hủy dữ liệu, thì hãy tránh xa --force... những điều tồi tệ có thể xảy ra .

Đây là lý do tại sao --force-with-leasecó phần an toàn hơn.


13
Hãy cẩn thận với "sửa chữa" đó, vì nếu họ có bất kỳ cam kết nào, không được đánh dấu thì họ sẽ bị "mất" ( mất thực sự có nghĩa là mồ côi , nhưng việc phục hồi chúng là không rõ ràng).
Andrew Marshall

1
bạn có thể muốn chỉ định tên chi nhánh khi bạn đẩy - lực lượng, nếu không bạn có thể đẩy nhiều hơn bạn mong đợi.
dùng693960

1
@ user693960: Git sẽ chỉ đẩy những gì bạn định cấu hình để đẩy.
Dietrich Epp

10
Đơn giản là git push --forcekhông có tùy chọn <repository> và <Branch> cũng hoạt động, nếu bạn đã thiết lập ngược dòng.
ahnbizcad

2
Bạn có thể cho một ví dụ về <repository>? Phải originkhông org/repo? Hay chỉ repo?
MikeSchinkel

440

Chỉ cần nói:

git commit --amend -m "New commit message"

và sau đó

git push --force

8
Trong trường hợp của tôi git push origin <BRANCH-NAME>không hoạt động, tôi đã phải sử dụng git push --forcenhư được giải thích trong câu trả lời được chấp nhận.
Gabriel

1
điều này không làm việc cho tôi. phải cho chúng tôi git push --force, nếu không thì sự thúc đẩy không đi qua.
ahnbizcad

4
@ahnbizcad, nó nên hoạt động. Chỉ cần chắc chắn rằng tên chi nhánh là chính xác.
William

3
Tôi cổ vũ cho sự đơn giản trong lời giải thích của bạn! Tôi sử dụng nó nhiều hơn thường xuyên
Vasikos

3
Tôi đã áp dụng thành công các lệnh này chỉ sau khi tạm thời "không bảo vệ" chi nhánh của mình, điều này đã xảy ra trong dự án được lưu trữ trên GitLab của tôi. Nếu bạn gặp phải vấn đề này, trước khi áp dụng các lệnh này, vui lòng tham khảo stackoverflow.com/a/32267118/1423345 này để "không bảo vệ" chi nhánh và bạn có thể "bảo vệ" lại nó sau khi sửa đổi thông điệp cam kết :)
John

262

Để chỉnh sửa một cam kết khác với lần gần đây nhất:

Bước 1 : git rebase -i HEAD~nđể thực hiện rebase tương tác cho các lần xác nhận cuối cùng nbị ảnh hưởng. (tức là nếu bạn muốn thay đổi thông điệp cam kết 3 lần quay lại, hãy làm git rebase -i HEAD~3)

git sẽ bật lên một trình soạn thảo để xử lý các cam kết đó, hãy chú ý lệnh này:

#  r, reword = use commit, but edit the commit message

đó chính xác là chúng ta cần!

Bước2 : Thay đổi pickthành rnhững cam kết mà bạn muốn cập nhật tin nhắn. Đừng bận tâm thay đổi thông điệp cam kết ở đây, nó sẽ bị bỏ qua. Bạn sẽ làm điều đó ở bước tiếp theo. Lưu và đóng trình chỉnh sửa.

Lưu ý rằng nếu bạn chỉnh sửa 'kế hoạch' rebase của mình nhưng nó không bắt đầu quá trình cho phép bạn đổi tên các tệp, hãy chạy:

git rebase --continue

Nếu bạn muốn thay đổi trình soạn thảo văn bản được sử dụng cho phiên tương tác (ví dụ: từ vi mặc định sang nano), hãy chạy:

GIT_EDITOR=nano git rebase -i HEAD~n

Bước 3 : Git sẽ bật lên một trình soạn thảo khác cho mọi sửa đổi bạn đặt rtrước đó. Cập nhật thông điệp cam kết theo ý muốn, sau đó lưu và đóng trình chỉnh sửa.

Bước 4 : Sau khi tất cả các thông điệp cam kết được cập nhật. bạn có thể muốn làm gì git push -fđể cập nhật từ xa.


21
Điều này nên được chấp nhận câu trả lời vì nó cho khả năng thay đổi các cam kết khác hơn so với cam kết gần đây nhất, không giống như câu trả lời được chấp nhận. Bạn đã cứu ngày của tôi. Cảm ơn bạn!
xZero

1
Chọn n = 3 cho 3 lần xác nhận gần nhất:git rebase -i HEAD~3
HeikoS

Nếu bạn chỉnh sửa 'kế hoạch' rebase của bạn nhưng nó không bắt đầu quá trình cho phép bạn đổi tên các tệp, hãy chạy git rebase --continue. Và nếu bạn muốn thay đổi trình soạn thảo văn bản được sử dụng cho phiên tương tác (ví dụ: từ mặc định vithành nano), hãy chạy GIT_EDITOR=nano git rebase -i HEAD~n.
Jamie Birch

Tôi chỉnh sửa nó để thêm một chút thông tin. Xin vui lòng xem qua. Đây là câu trả lời cho những gì tôi muốn làm, nhưng tôi đã cuộn nó bởi vì nó không có tiêu đề.
Kip

Tôi đã thực hiện một chỉnh sửa được đề xuất để đưa nhận xét hữu ích từ @JamieBirch vào câu trả lời, có thể muốn xem lại.
Notts90 hỗ trợ Monica

44

Sử dụng hai bước này trong bảng điều khiển:

git commit --amend -m "new commit message"

và sau đó

git push -f

Làm xong :)


Thx, đó có phải là các bước chỉ để sửa đổi bình luận cuối cùng hay nó cũng có thể được sử dụng cho các bình luận cũ hơn?
Jay

@Jay xin lỗi vì trả lời trễ, các bước này chỉ để sửa đổi tin nhắn cam kết cuối cùng.
Abdul Rizwan

19

Cần lưu ý rằng nếu bạn sử dụng push --forcevới refs mutipl, kết quả là TẤT CẢ chúng sẽ được sửa đổi. Hãy chắc chắn chú ý đến nơi git repo của bạn được cấu hình để đẩy tới. May mắn thay, có một cách để bảo vệ quá trình một chút, bằng cách chỉ định một nhánh duy nhất để cập nhật. Đọc từ các trang git man:

Lưu ý rằng - Force áp dụng cho tất cả các ref được đẩy, do đó sử dụng nó với push.default được đặt thành khớp hoặc với nhiều đích đẩy được định cấu hình từ xa. *. Push có thể ghi đè lên các ref khác ngoài nhánh hiện tại (bao gồm cả refs cục bộ nghiêm ngặt đằng sau đối tác từ xa của họ). Để buộc một lực đẩy chỉ vào một nhánh, hãy sử dụng dấu + phía trước refspec để đẩy (ví dụ: git đẩy gốc + master để đẩy một cú đẩy vào nhánh chính).


3
Lưu ý rất quan trọng.
peterh - Phục hồi Monica

không có câu trả lời bắt buộc nào phù hợp với tôi, vì tôi không có quyền ForcePush trên máy chủ. Thay vào đó, tôi muốn thực hiện một cam kết thay đổi thông điệp cam kết trước đó. Tôi có thể viết "thông điệp cam kết đã thay đổi" vào phần bình luận của cam kết đó.
Nurettin

11

Nếu bạn muốn sửa đổi một cam kết cũ hơn, không phải là cam kết cuối cùng, bạn sẽ cần sử dụng rebaselệnh như được giải thích ở đây, trang trợ giúp Github , trên Sửa đổi tin nhắn của các tin nhắn cam kết cũ hoặc nhiều phần


11

Lệnh 1 .

git commit --amend -m "New and correct message"

Sau đó,

Lệnh 2 .

git push origin --force

8
git commit --amend

sau đó chỉnh sửa và thay đổi tin nhắn trong cửa sổ hiện tại. Sau đó làm

git push --force-with-lease

2

Một tùy chọn khác là tạo thêm một "errata commit" (và đẩy) tham chiếu đến đối tượng cam kết có lỗi - cam kết errata mới cũng cung cấp sự điều chỉnh. Một cam kết errata là một cam kết không có thay đổi mã đáng kể nhưng một thông báo cam kết quan trọng - ví dụ: thêm một ký tự khoảng trắng vào tệp readme của bạn và cam kết thay đổi đó với thông điệp cam kết quan trọng hoặc sử dụng tùy chọn git --allow-empty. Nó chắc chắn dễ dàng và an toàn hơn so với việc nổi loạn, nó không sửa đổi lịch sử thực sự và nó giữ cho cây nhánh sạch sẽ (sử dụngamendcũng là một lựa chọn tốt nếu bạn đang sửa lỗi cam kết gần đây nhất, nhưng cam kết errata có thể là một lựa chọn tốt cho các cam kết cũ hơn). Loại điều này rất hiếm khi xảy ra mà chỉ cần ghi lại lỗi là đủ tốt. Trong tương lai, nếu bạn cần tìm kiếm thông qua nhật ký git cho một từ khóa tính năng, cam kết ban đầu (có lỗi) có thể không xuất hiện do từ khóa sai được sử dụng trong cam kết ban đầu đó (lỗi chính tả) - tuy nhiên, từ khóa sẽ xuất hiện trong cam kết errata mà sau đó sẽ đưa bạn đến cam kết ban đầu có lỗi đánh máy. Đây là một ví dụ:

$ git nhật ký
cam kết 0c28141c68adae276840f17ccd4766542c33cf1d
Tác giả: Đầu tiên cuối cùng 
Ngày: Thứ Tư 8 tháng 8 15:55:52 2018 -0600

    Errata cam kết:
    Cam kết này không có thay đổi mã đáng kể.
    Cam kết này chỉ được cung cấp để ghi lại sự điều chỉnh cho thông điệp cam kết trước đó.
    Điều này liên quan đến cam kết đối tượng e083a7abd8deb5776cb304fa13731a4182a24be1
    Thông báo cam kết không chính xác:
        Thay đổi màu nền thành màu đỏ
    Sửa lỗi (* thay đổi được tô sáng *):
        Thay đổi màu nền thành * xanh *

cam kết 032d0ff0601bff79bdef3c6f0a02ebfa061c4ad4
Tác giả: Đầu tiên cuối cùng 
Ngày: Thứ Tư 8 tháng 8 15:43:16 2018 -0600

    Một số tin nhắn cam kết tạm thời

cam kết e083a7abd8deb5776cb304fa13731a4182a24be1
Tác giả: Đầu tiên cuối cùng 
Ngày: Thứ Tư 8 tháng 8 13:31:32 2018 -0600

    Thay đổi màu nền thành màu đỏ

cướp, điều này có vẻ đầy hứa hẹn. bạn có thể hiển thị các lệnh cần thiết để thực hiện một "errata commit". chỉ bài đăng này hiển thị trong google về các điều khoản này.
Jim

1
Một cam kết errata sai chỉ đơn giản là một cam kết bình thường với một thông báo tham chiếu đến cam kết sai lầm trước đó, ghi lại và cung cấp một sửa chữa cho lỗi trước đó. git commit -m “fixed feature A”(Giả sử git cung cấp ID cam kết này của e3ab7312 ... ... (sau này bạn nhận ra tin nhắn của mình không chính xác nên giờ hãy thực hiện thay đổi không quan trọng đối với tệp như thêm khoảng trắng vào tệp readme hoặc sử dụng —allow-emptytùy chọn git). .. git commit -m “Errata commit for previous commit e3ab7312... original message should have been ‘fixed feature *B*’'' '
rob_7cc

1
... nếu sau này bạn cần tìm kiếm nhật ký git để tham khảo tính năng Bv, thì cam kết errata sẽ hiển thị, nhưng thông báo cam kết errata chứa tham chiếu đến ID xác thực ban đầu cung cấp khả năng truy nguyên đầy đủ. BTW thuật ngữ Cam errata cam kết không có gì đặc biệt (không có lệnh nào errataata cũng không có tùy chọn trong git) ... đó chỉ là thuật ngữ của tôi cho một cam kết bình thường cung cấp một sửa chữa cho một cam kết trước đó có lỗi / lỗi đánh máy.
rob_7cc

cướp, làm việc rất tốt Tôi đã có thể thêm một cam kết trống mới với mô tả chính xác, trỏ đến cam kết ban đầu, bằng cách sử dụng SHA. bây giờ, cả hai được hiển thị trong 'chuỗi git' của tôi cho các mô-đun. cảm ơn!
Jim

Tôi rất vui vì đã làm việc cho bạn. Tôi sử dụng kỹ thuật tương tự để sửa lỗi trong các thông điệp cam kết. Thay vào đó, tôi mới phát hiện ra git notes Điều này sẽ phục vụ cùng một mục đích như một "cam kết errata". Chỉ cần thêm một ghi chú vào một cam kết trước đó để chú thích hoặc sửa bất kỳ lỗi nào trong thông báo cam kết: https://git-scm.com/docs/git-notes
rob_7cc

0

Điều này làm việc cho tôi khá tốt,

nguồn gốc thanh toán git / tên chi nhánh

nếu bạn đã ở trong chi nhánh thì tốt hơn là nên kéo hoặc rebase

git pull

hoặc là

git -c core.quotepath=false fetch origin --progress --prune

Sau này bạn có thể sử dụng

git commit --amend -m "Your message here"

hoặc nếu bạn muốn mở trình soạn thảo văn bản thì hãy sử dụng

git commit --amend

Tôi sẽ thích sử dụng trình soạn thảo văn bản nếu bạn có nhiều ý kiến. Bạn có thể đặt trình soạn thảo văn bản ưa thích của mình bằng lệnh

git config --global core.editor your_preffered_editor_here

Dù sao, khi bạn hoàn thành việc thay đổi thông điệp cam kết, hãy lưu nó và thoát

và sau đó chạy

git push --force

Và bạn đã hoàn thành


0

thông tin bổ sung cho cùng một vấn đề nếu bạn đang sử dụng đường ống bitbucket

chỉnh sửa tin nhắn của bạn

git commit --amend

đẩy đến sever

git push --force <repository> <branch>

sau đó thêm - Force vào lệnh đẩy của bạn trên đường ống

git ftp push --force

Điều này sẽ xóa (các) cam kết trước đó của bạn và đẩy cam kết hiện tại của bạn.

loại bỏ - lực lượng sau lần đẩy đầu tiên

tôi đã thử nó trên đường ống bitbucket và nó hoạt động tốt

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.