Xóa cam kết cụ thể


287

Tôi đang làm việc với một người bạn trong một dự án và anh ta đã chỉnh sửa một loạt các tệp không nên chỉnh sửa. Bằng cách nào đó tôi đã hợp nhất công việc của anh ấy với tôi, hoặc khi tôi kéo nó, hoặc khi tôi cố gắng chỉ chọn các tệp cụ thể mà tôi muốn. Tôi đã tìm kiếm và chơi trong một thời gian dài, cố gắng tìm ra cách loại bỏ các cam kết có chứa các chỉnh sửa cho các tệp đó, nó dường như là một sự thay đổi giữa hoàn nguyên và phản hồi, và không có ví dụ đơn giản nào, và tài liệu giả định tôi biết nhiều hơn tôi làm.

Vì vậy, đây là một phiên bản đơn giản của câu hỏi:

Đưa ra kịch bản sau đây, làm cách nào để xóa cam kết 2?

$ mkdir git_revert_test && cd git_revert_test

$ git init
Initialized empty Git repository in /Users/josh/deleteme/git_revert_test/.git/

$ echo "line 1" > myfile

$ git add -A

$ git commit -m "commit 1"
[master (root-commit) 8230fa3] commit 1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 myfile

$ echo "line 2" >> myfile

$ git commit -am "commit 2"
[master 342f9bb] commit 2
 1 files changed, 1 insertions(+), 0 deletions(-)

$ echo "line 3" >> myfile

$ git commit -am "commit 3"
[master 1bcb872] commit 3
 1 files changed, 1 insertions(+), 0 deletions(-)

Kết quả mong đợi là

$ cat myfile
line 1
line 3

Đây là một ví dụ về cách tôi đã cố gắng hoàn nguyên

$ git revert 342f9bb
Automatic revert failed.  After resolving the conflicts,
mark the corrected paths with 'git add <paths>' or 'git rm <paths>'
and commit the result.

4
Nếu bất cứ ai tìm thấy điều này trong khi tìm kiếm cùng một vấn đề, đây là những gì tôi đã làm: Sao chép và dán. Nghiêm túc. Đã dành hơn 6 giờ cố gắng để làm cho các giải pháp được đề xuất để làm việc, nhưng không có kết quả. Cuối cùng, tôi đã hết thời gian, lấy bản gốc và chỉ sao chép / dán khoảng 20 tệp. Mất chưa đầy 5 phút và mọi thứ vẫn ổn kể từ đó (ngay cả khi các tệp đó đang được hợp nhất với các thay đổi trong các nhánh khác đã xảy ra trước fiasco này). Tôi đề nghị bạn thực hiện phương pháp này cũng. Không chỉ đơn giản nhất, tôi cũng nghi ngờ đó là điều duy nhất hoạt động.
Joshua Cheek

Tôi đã phải đối mặt với một vấn đề tương tự, nhưng có lẽ phức tạp hơn: có một chi nhánh với hàng trăm cam kết mà tôi muốn dẹp. Thật không may, các cam kết từ một chi nhánh khác đã được sáp nhập trở lại vào chi nhánh tại một điểm trung gian, do đó, một "sự hòa nhập" là cần thiết trước khi tôi có thể đè bẹp. Tôi đã đi xuống một con đường tương tự như được đề xuất bởi tk bên dưới (chọn cherry + sử dụng ký hiệu phạm vi), nhưng nó tạo ra xung đột trong một số tệp khác. Cuối cùng, sao chép và dán + một vài chỉnh sửa thủ công là con đường dễ nhất và dễ đoán nhất về phía trước. Chắc chắn đáng để xem xét nếu bạn thấy mình dành quá nhiều thời gian cho việc này.
Federico

Câu trả lời:


73

Thuật toán mà Git sử dụng khi tính toán diff để được hoàn nguyên yêu cầu rằng

  1. các dòng được hoàn nguyên không được sửa đổi bởi bất kỳ cam kết nào sau này.
  2. rằng không có bất kỳ cam kết "liền kề" nào khác trong lịch sử.

Định nghĩa của "liền kề" dựa trên số dòng mặc định từ một khác biệt ngữ cảnh, là 3. Vì vậy, nếu 'myfile' được xây dựng như thế này:

$ cat >myfile <<EOF
line 1
junk
junk
junk
junk
line 2
junk
junk
junk
junk
line 3
EOF
$ git add myfile
$ git commit -m "initial check-in"
 1 files changed, 11 insertions(+), 0 deletions(-)
 create mode 100644 myfile

$ perl -p -i -e 's/line 2/this is the second line/;' myfile
$ git commit -am "changed line 2 to second line"
[master d6cbb19] changed line 2
 1 files changed, 1 insertions(+), 1 deletions(-)

$ perl -p -i -e 's/line 3/this is the third line/;' myfile
$ git commit -am "changed line 3 to third line"
[master dd054fe] changed line 3
 1 files changed, 1 insertions(+), 1 deletions(-)

$ git revert d6cbb19
Finished one revert.
[master 2db5c47] Revert "changed line 2"
 1 files changed, 1 insertions(+), 1 deletions(-)

Sau đó, tất cả hoạt động như mong đợi.

Câu trả lời thứ hai rất thú vị. Có một tính năng chưa được phát hành chính thức (mặc dù nó có sẵn trong Git v1.7.2-rc2) được gọi là Chiến lược hoàn nguyên. Bạn có thể gọi git như thế này:

git Revert - giải quyết chiến lược <commit>

và nó nên làm một công việc tốt hơn để tìm ra những gì bạn có ý nghĩa. Tôi không biết danh sách các chiến lược khả dụng là gì và tôi cũng không biết định nghĩa của bất kỳ chiến lược nào.


1
perl -prất hữu ích để viết các chương trình rất ngắn (một dòng) lặp và chuyển đầu vào của chúng qua đầu ra, tương tự như sed. perl -iđược sử dụng để chỉnh sửa các tập tin tại chỗ . perl -elà làm thế nào để gửi mã được đánh giá .
Hal Eisen

281

Có bốn cách để làm như vậy:

  • Cách sạch sẽ, hoàn nguyên nhưng tiếp tục đăng nhập hoàn nguyên:

    git revert --strategy resolve <commit>
    
  • Cách khắc nghiệt, loại bỏ hoàn toàn chỉ cam kết cuối cùng:

    git reset --soft "HEAD^"
    

Lưu ý: Tránh git reset --hardvì nó cũng sẽ loại bỏ tất cả các thay đổi trong tệp kể từ lần xác nhận cuối cùng. Nếu --softkhông hoạt động, thay vì thử --mixedhoặc --keep.

  • Rebase (hiển thị nhật ký của 5 lần xác nhận gần nhất và xóa các dòng bạn không muốn hoặc sắp xếp lại hoặc xóa nhiều xác nhận trong một hoặc làm bất cứ điều gì bạn muốn, đây là một công cụ rất linh hoạt):

    git rebase -i HEAD~5
    

Và nếu một lỗi được thực hiện:

git rebase --abort
  • Rebase nhanh: chỉ xóa một cam kết cụ thể bằng id của nó:

    git rebase --onto commit-id^ commit-id
    
  • Lựa chọn thay thế: bạn cũng có thể thử:

    git cherry-pick commit-id
    
  • Một lựa chọn khác:

    git revert --no-commit
    
  • Như một phương sách cuối cùng, nếu bạn cần hoàn toàn tự do chỉnh sửa lịch sử (ví dụ: vì git không cho phép bạn chỉnh sửa những gì bạn muốn), bạn có thể sử dụng ứng dụng nguồn mở rất nhanh này : reposurgeon .

Lưu ý: tất nhiên, tất cả những thay đổi này được thực hiện cục bộ, git pushsau đó bạn nên áp dụng các thay đổi cho điều khiển từ xa. Và trong trường hợp repo của bạn không muốn xóa cam kết ("không cho phép chuyển tiếp nhanh", điều này xảy ra khi bạn muốn xóa một cam kết bạn đã đẩy), bạn có thể sử dụng git push -fđể đẩy các thay đổi.

Lưu ý2: nếu làm việc trên một nhánh và bạn cần phải đẩy, bạn tuyệt đối nên tránh git push --forcevì điều này có thể ghi đè lên các nhánh khác (nếu bạn đã thực hiện thay đổi trong chúng, ngay cả khi thanh toán hiện tại của bạn ở nhánh khác). Thích luôn luôn chỉ định nhánh từ xa khi bạn buộc đẩy : git push --force origin your_branch.


Dựa trên các đề xuất của @gabious: thực hiện "git rebase -i Head ~ 2". Bây giờ bạn có một vài lựa chọn. Trong vim bạn có thể thấy một số dòng nhận xét: một trong số chúng cho bạn biết rằng bạn chỉ cần xóa một dòng (đó phải là cam kết bạn muốn loại bỏ) và cam kết này sẽ bị xóa cùng với nhật ký của bạn.
Mèo Ilker

git Revert - giải quyết chiến lược <commit>. Lệnh này hoạt động với tôi. cảm ơn :)
Swathin

2
git rebase -i HEAD~5đã làm cho tôi. Sau đó, tôi chỉ cần xóa (các) cam kết mà tôi không cần và tôi đã có thể giải quyết vấn đề trong vòng chưa đầy 30 giây. Cảm ơn bạn.
lv10

117

Đây là một giải pháp dễ dàng:

git rebase -i HEAD~x

(Lưu ý: xlà số lần xác nhận)

khi thực hiện tập tin notepad sẽ mở ra. Nhập dropbên cạnh cam kết của bạn.
Nếu bạn không biết Vim, chỉ cần nhấp vào từng từ bạn muốn chỉnh sửa và sau đó nhấn phím "I" (đối với chế độ chèn). Khi bạn nhập xong, nhấn phím "esc" để thoát chế độ chèn.



nhập mô tả hình ảnh ở đây

và thế là xong, bạn đã hoàn thành ... Chỉ cần đồng bộ hóa bảng điều khiển git và các thay đổi sẽ được đẩy lên từ xa.

Nếu cam kết bạn thả đã có trên điều khiển từ xa, bạn sẽ phải buộc đẩy. Vì - lực lượng được coi là có hại , sử dụng git push --force-with-lease.


Có cách nào tốt để tìm hiểu 'x' nên là gì nếu bạn chỉ biết hàm băm của câu hỏi?
jlewkovich

1
Đối với người có tâm lý cpp: x (không có cam kết) là bao gồm. ví dụ: Head ~ 4 bao gồm 4 lần xác nhận cuối cùng.
Kỹ sư Herpes miễn phí

đề nghị hoàn hảo. chỉ muốn thêm, điều này cũng loại bỏ các thay đổi từ cam kết bị hủy.
celerno

đã cố gắng hoàn nguyên 3 lần xác nhận: git rebase -i ĐẦU-3 gặp lỗi nghiêm trọng: Cần một phiên bản duy nhất không hợp lệ ngược dòng 'ĐẦU-3'
Ustin

1
@Ustin nó ~ 3 không -3
JD-V

37

Sự lựa chọn của bạn là giữa

  1. giữ lỗi và giới thiệu một sửa chữa và
  2. loại bỏ lỗi và thay đổi lịch sử.

Bạn nên chọn (1) nếu bất kỳ ai khác đã thay đổi lỗi và (2) nếu lỗi được giới hạn ở một nhánh riêng không được đẩy.

Git Revert là một công cụ tự động để làm (1), nó tạo ra một cam kết mới hoàn tác một số cam kết trước đó. Bạn sẽ thấy lỗi và xóa trong lịch sử dự án nhưng những người lấy từ kho lưu trữ của bạn sẽ không gặp vấn đề khi họ cập nhật. Nó không hoạt động theo cách tự động trong ví dụ của bạn, do đó bạn cần chỉnh sửa 'myfile' (để xóa dòng 2), thực hiện git add myfilegit commitxử lý xung đột. Sau đó, bạn sẽ kết thúc với bốn lần xác nhận trong lịch sử của mình, với cam kết 4 hoàn lại cam kết 2.

Nếu không ai quan tâm rằng lịch sử của bạn thay đổi, bạn có thể viết lại và xóa cam kết 2 (lựa chọn 2). Cách dễ dàng để làm điều này là sử dụng git rebase -i 8230fa3. Điều này sẽ đưa bạn vào một trình soạn thảo và bạn có thể chọn không bao gồm các cam kết sai lầm bằng cách xóa cam kết (và giữ "chọn" bên cạnh các thông báo cam kết khác. Hãy đọc về hậu quả của việc này .


Rebase có thể là khó khăn, vì có vẻ như đã có một sự hợp nhất.
Cascabel

3
git rebase -i 8230fa3 và xóa dòng cam kết có hiệu quả với tôi với những thay đổi chỉ cục bộ của tôi. Cảm ơn!
Samuel

26

Bổ sung 1

Trước tiên, lấy hàm băm cam kết (ví dụ: 1406cd61) mà bạn cần hoàn nguyên. sửa chữa đơn giản sẽ dưới đây lệnh,

$ git revert 1406cd61

nếu bạn đã cam kết nhiều thay đổi liên quan đến các tệp 1406cd61 sau cam kết 1406cd61, Lệnh đơn giản trên sẽ không hoạt động. Sau đó, bạn phải làm các bước dưới đây, đó là hái anh đào.

Bổ sung 2

Vui lòng thực hiện theo các hành động dưới đây, vì chúng tôi đang sử dụng - buộc bạn cần có quyền quản trị đối với repo git để thực hiện việc này.

Bước 1: Tìm cam kết trước khi cam kết bạn muốn xóagit log

Bước 2: Thanh toán cam kếtgit checkout <commit hash>

Bước 3: Tạo chi nhánh mới bằng cam kết thanh toán hiện tại của bạngit checkout -b <new branch>

Bước 4: Bây giờ bạn cần thêm cam kết sau khi xóa cam kếtgit cherry-pick <commit hash>

Bước 5: Bây giờ lặp lại Bước 4 cho tất cả các cam kết khác mà bạn muốn giữ.

Bước 6: Khi tất cả các cam kết đã được thêm vào chi nhánh mới của bạn và đã được cam kết. Kiểm tra xem mọi thứ có ở trạng thái chính xác và hoạt động như dự định không. Kiểm tra lại mọi thứ đã được cam kết:git status

Bước 7: Chuyển sang chi nhánh bị hỏng của bạngit checkout <broken branch>

Bước 8: Bây giờ thực hiện thiết lập lại cứng trên nhánh bị hỏng theo cam kết trước khi bạn muốn xóagit reset --hard <commit hash>

Bước 9: Hợp nhất chi nhánh cố định của bạn vào chi nhánh nàygit merge <branch name>

Bước 10: Đẩy các thay đổi đã hợp nhất trở lại nguồn gốc. CẢNH BÁO: Điều này sẽ ghi đè lên repo từ xa!git push --force origin <branch name>

Bạn có thể thực hiện quy trình mà không cần tạo chi nhánh mới bằng cách thay thế Bước 2 & 3 bằng Bước 8 sau đó không thực hiện Bước 7 & 9.


1
Cách tiếp cận đầu tiên làm việc như một lá bùa. Nó bao gồm cho bạn một cam kết xác định rằng cam kết mong muốn của bạn đã được hoàn nguyên, điều này thực sự tốt cho mục đích theo dõi.
suarsenegger

18

Bạn có thể loại bỏ các cam kết không mong muốn với git rebase. Giả sử bạn đã bao gồm một số cam kết từ nhánh chủ đề của đồng nghiệp vào nhánh chủ đề của mình, nhưng sau đó quyết định bạn không muốn những cam kết đó.

git checkout -b tmp-branch my-topic-branch  # Use a temporary branch to be safe.
git rebase -i master  # Interactively rebase against master branch.

Tại thời điểm này, trình soạn thảo văn bản của bạn sẽ mở giao diện rebase tương tác. Ví dụ

git-rebase-todo

  1. Xóa các cam kết bạn không muốn bằng cách xóa các dòng của họ
  2. Lưu và thoát

Nếu cuộc nổi loạn không thành công, hãy xóa chi nhánh tạm thời và thử một chiến lược khác. Nếu không, tiếp tục với các hướng dẫn sau đây.

git checkout my-topic-branch
git reset --hard tmp-branch  # Overwrite your topic branch with the temp branch.
git branch -d tmp-branch  # Delete the temporary branch.

Nếu bạn đang đẩy nhánh chủ đề của mình đến một điều khiển từ xa, bạn có thể cần phải đẩy mạnh vì lịch sử cam kết đã thay đổi. Nếu những người khác đang làm việc trên cùng một chi nhánh, hãy cho họ một cái đầu lên.


Bạn có thể vui lòng cho một ví dụ về 'thử một chiến lược khác' không?
pfabri

@pfabri, ví dụ, bạn có thể chọn hai phạm vi cam kết trong đó bạn bỏ qua các cam kết xấu. Bạn có thể hoàn nguyên các cam kết xấu. Bạn có thể tránh sử dụng giải pháp git bằng cách thậm chí hoàn tác thủ công các thay đổi hoặc bắt đầu từ một nhánh mới mà không có cam kết xấu và làm lại thủ công các thay đổi tốt. Nếu cam kết xấu chứa dữ liệu nhạy cảm, bạn sẽ cần một chiến lược cẩn thận hơn: help.github.com/en/articles/iêu
Dennis

8

Từ các câu trả lời khác ở đây, tôi đã bối rối với cách git rebase -isử dụng để loại bỏ một cam kết, vì vậy tôi hy vọng sẽ ổn khi ghi lại trường hợp thử nghiệm của mình ở đây (rất giống với OP).

Đây là bashtập lệnh mà bạn có thể dán vào để tạo kho lưu trữ kiểm tra trong /tmpthư mục:

set -x

rm -rf /tmp/myrepo*
cd /tmp

mkdir myrepo_git
cd myrepo_git
git init
git config user.name me
git config user.email me@myself.com

mkdir folder
echo aaaa >> folder/file.txt
git add folder/file.txt
git commit -m "1st git commit"

echo bbbb >> folder/file.txt
git add folder/file.txt
git commit -m "2nd git commit"

echo cccc >> folder/file.txt
git add folder/file.txt
git commit -m "3rd git commit"

echo dddd >> folder/file.txt
git add folder/file.txt
git commit -m "4th git commit"

echo eeee >> folder/file.txt
git add folder/file.txt
git commit -m "5th git commit"

Tại thời điểm này, chúng tôi có một file.txtvới các nội dung sau:

aaaa
bbbb
cccc
dddd
eeee

Tại thời điểm này, CHÍNH nằm ở lần xác nhận thứ 5, ĐẦU ~ 1 sẽ là lần thứ 4 - và ĐẦU ~ 4 sẽ là lần cam kết thứ nhất (vì vậy, ĐẦU ~ 5 sẽ không tồn tại). Giả sử chúng tôi muốn xóa cam kết thứ 3 - chúng tôi có thể ban hành lệnh này trong myrepo_gitthư mục:

git rebase -i HEAD~4

( Lưu ý rằng git rebase -i HEAD~5kết quả với. "Chết người: Cần một phiên bản duy nhất; không hợp lệ ĐẦU ~ 5 ngược dòng" ) Một soạn thảo văn bản (xem ảnh chụp màn hình trong câu trả lời @Dennis' ) sẽ mở ra với những nội dung:

pick 5978582 2nd git commit
pick 448c212 3rd git commit
pick b50213c 4th git commit
pick a9c8fa1 5th git commit

# Rebase b916e7f..a9c8fa1 onto b916e7f
# ...

Vì vậy, chúng tôi nhận được tất cả các cam kết kể từ (nhưng không bao gồm ) ĐẦU ~ 4 được yêu cầu của chúng tôi. Xóa dòng pick 448c212 3rd git commitvà lưu tệp; bạn sẽ nhận được phản hồi này từ git rebase:

error: could not apply b50213c... 4th git commit

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
Could not apply b50213c... 4th git commit

Tại thời điểm này, mở myrepo_git / folder/file.txttrong trình soạn thảo văn bản; bạn sẽ thấy nó đã được sửa đổi:

aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit

Về cơ bản, gitthấy rằng khi ĐẦU đạt đến cam kết thứ 2, có nội dung của aaaa+ bbbb; và sau đó nó có một bản vá thêm cccc+ ddddmà nó không biết cách thêm vào nội dung hiện có.

Vì vậy, ở đây gitkhông thể quyết định cho bạn - chính bạn là người phải đưa ra quyết định: bằng cách xóa cam kết thứ 3, bạn có thể giữ các thay đổi được giới thiệu bởi nó (ở đây, dòng cccc) - hoặc bạn không. Nếu bạn không, chỉ cần xóa các dòng bổ sung - bao gồm cccc- trong folder/file.txtviệc sử dụng trình soạn thảo văn bản, để nó trông như thế này:

aaaa
bbbb
dddd

... và sau đó tiết kiệm folder/file.txt. Bây giờ bạn có thể đưa ra các lệnh sau trong myrepo_gitthư mục:

$ nano folder/file.txt  # text editor - edit, save
$ git rebase --continue
folder/file.txt: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add

Ah - vì vậy để đánh dấu mà chúng tôi đã giải quyết được mâu thuẫn, chúng tôi phải git add sự folder/file.txt, trước khi thực hiện git rebase --continue:

$ git add folder/file.txt
$ git rebase --continue

Ở đây, một trình soạn thảo văn bản sẽ mở lại, hiển thị dòng 4th git commit- ở đây chúng ta có cơ hội thay đổi thông điệp cam kết (trong trường hợp này có thể được thay đổi một cách có ý nghĩa 4th (and removed 3rd) commithoặc tương tự). Giả sử bạn không muốn - vì vậy chỉ cần thoát trình soạn thảo văn bản mà không lưu; một khi bạn làm điều đó, bạn sẽ nhận được:

$ git rebase --continue
[detached HEAD b8275fc] 4th git commit
 1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.

Tại thời điểm này, bây giờ bạn có một lịch sử như thế này (mà bạn cũng có thể kiểm tra bằng nói gitk .hoặc các công cụ khác) về nội dung của folder/file.txt(với, rõ ràng, dấu thời gian không thay đổi của các cam kết ban đầu):

1st git commit  |  +aaaa
----------------------------------------------
2nd git commit  |   aaaa
                |  +bbbb
----------------------------------------------
4th git commit  |   aaaa
                |   bbbb
                |  +dddd
----------------------------------------------
5th git commit  |   aaaa
                |   bbbb
                |   dddd
                |  +eeee

Và nếu trước đây, chúng tôi đã quyết định giữ dòng cccc(nội dung của cam kết git thứ 3 mà chúng tôi đã xóa), chúng tôi sẽ có:

1st git commit  |  +aaaa
----------------------------------------------
2nd git commit  |   aaaa
                |  +bbbb
----------------------------------------------
4th git commit  |   aaaa
                |   bbbb
                |  +cccc
                |  +dddd
----------------------------------------------
5th git commit  |   aaaa
                |   bbbb
                |   cccc
                |   dddd
                |  +eeee

Chà, đây là kiểu đọc mà tôi hy vọng tôi đã tìm thấy, để bắt đầu tìm hiểu cách thức git rebasehoạt động trong việc xóa các cam kết / sửa đổi; vì vậy hy vọng nó cũng có thể giúp đỡ người khác ...


Thật là một cuộc dạo chơi vô giá - trường hợp sử dụng chính xác mà tôi đang vật lộn, điều này đã giúp tôi rất nhiều.
pfabri

2

Vì vậy, có vẻ như cam kết xấu đã được kết hợp trong một cam kết hợp nhất tại một số điểm. Cam kết hợp nhất của bạn đã được kéo chưa? Nếu có, thì bạn sẽ muốn sử dụng git revert; bạn sẽ phải nghiến răng và vượt qua những xung đột. Nếu không, thì bạn có thể hình dung là rebase hoặc hoàn nguyên, nhưng bạn có thể làm như vậy trước khi xác nhận hợp nhất, sau đó làm lại hợp nhất.

Không có nhiều sự giúp đỡ, chúng tôi có thể cung cấp cho bạn cho trường hợp đầu tiên, thực sự. Sau khi thử hoàn nguyên và thấy rằng máy tự động bị lỗi, bạn phải kiểm tra các xung đột và khắc phục chúng một cách thích hợp. Đây chính xác là quá trình tương tự như sửa chữa xung đột hợp nhất; bạn có thể sử dụng git statusđể xem các xung đột ở đâu, chỉnh sửa các tệp chưa được trộn, tìm các khối bị xung đột, tìm ra cách giải quyết chúng, thêm các tệp bị xung đột và cuối cùng là cam kết. Nếu bạn sử dụng git commitchính nó (không -m <message>), thông báo bật lên trong trình chỉnh sửa của bạn sẽ là thông báo mẫu được tạo bởi git revert; bạn có thể thêm một ghi chú về cách bạn đã khắc phục các xung đột, sau đó lưu và thoát để cam kết.

Đối với trường hợp thứ hai, khắc phục sự cố trước khi hợp nhất của bạn, có hai nhóm con, tùy thuộc vào việc bạn đã thực hiện nhiều công việc hơn kể từ khi hợp nhất. Nếu bạn không có, bạn có thể chỉ cần git reset --hard HEAD^loại bỏ hợp nhất, thực hiện hoàn nguyên, sau đó làm lại hợp nhất. Nhưng tôi đoán bạn có. Vì vậy, cuối cùng bạn sẽ làm một cái gì đó như thế này:

  • tạo một nhánh tạm thời ngay trước khi hợp nhất và kiểm tra nó
  • thực hiện hoàn nguyên (hoặc sử dụng git rebase -i <something before the bad commit> <temporary branch>để loại bỏ các cam kết xấu)
  • làm lại hợp nhất
  • khởi động lại công việc tiếp theo của bạn trở lại: git rebase --onto <temporary branch> <old merge commit> <real branch>
  • xóa chi nhánh tạm thời

1

Vì vậy, bạn đã thực hiện một số công việc và thúc đẩy nó, hãy gọi họ cam kết A và B. Đồng nghiệp của bạn cũng đã thực hiện một số công việc, cam kết C và D. Bạn đã hợp nhất công việc của bạn với bạn (hợp nhất E), sau đó tiếp tục làm việc, cam kết rằng, cũng vậy (cam kết F) và phát hiện ra rằng đồng nghiệp của bạn đã thay đổi một số thứ anh ta không nên có.

Vì vậy, lịch sử cam kết của bạn trông như thế này:

A -- B -- C -- D -- D' -- E -- F

Bạn thực sự muốn thoát khỏi C, D và D '. Vì bạn nói rằng bạn đã hợp nhất các đồng nghiệp của bạn làm việc với bạn, những cam kết này đã "ở ngoài đó", do đó, loại bỏ các cam kết bằng cách sử dụng, ví dụ như git rebase là không nên. Hãy tin tôi, tôi đã thử.

Bây giờ, tôi thấy hai cách:

  • nếu bạn chưa đẩy E và F cho đồng nghiệp hoặc bất kỳ ai khác (thường là máy chủ "gốc" của bạn), bạn vẫn có thể xóa chúng khỏi lịch sử trong thời điểm hiện tại. Đây là công việc của bạn mà bạn muốn tiết kiệm. Điều này có thể được thực hiện với một

    git reset D'
    

    (thay thế D 'bằng hàm băm cam kết thực tế mà bạn có thể nhận được từ một git log

    Tại thời điểm này, các cam kết E và F đã biến mất và các thay đổi là các thay đổi không được cam kết trong không gian làm việc cục bộ của bạn một lần nữa. Tại thời điểm này tôi sẽ di chuyển chúng đến một nhánh hoặc biến chúng thành một bản vá và lưu nó cho lần sau. Bây giờ, hoàn nguyên công việc của đồng nghiệp của bạn, tự động bằng git reverthoặc bằng tay. Khi bạn đã làm điều đó, phát lại công việc của bạn trên đó. Bạn có thể có các xung đột hợp nhất, nhưng ít nhất chúng sẽ nằm trong mã bạn đã viết, thay vì mã của đồng nghiệp.

  • Nếu bạn đã thúc đẩy công việc bạn đã làm sau khi đồng nghiệp cam kết, bạn vẫn có thể thử và lấy "bản vá ngược" bằng tay hoặc sử dụng git revert, nhưng vì công việc của bạn là "theo cách", nên có thể nói bạn sẽ nhận được nhiều xung đột hợp nhất và những cái khó hiểu hơn. Có vẻ như đó là những gì bạn đã kết thúc trong ...


0

git Revert - giải quyết chiến lược nếu cam kết là hợp nhất: sử dụng git Revert - giải pháp chiến lược -m 1

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.