Phá vỡ một cam kết trước đó thành nhiều cam kết


1224

Không tạo ra một nhánh và thực hiện một loạt các công việc thú vị trên một nhánh mới, có thể chia một cam kết thành một vài cam kết khác nhau sau khi nó được cam kết với kho lưu trữ cục bộ không?


36
Một nguồn tốt để tìm hiểu cách thực hiện việc này là Pro Git §6.4 Công cụ Git - Viết lại lịch sử , trong phần "Chia tách cam kết".

2
Các tài liệu được liên kết ở nhận xét trên là tuyệt vời, giải thích tốt hơn so với các câu trả lời dưới đây.
Blaisorblade

2
Tôi đề nghị sử dụng bí danh stackoverflow.com/a/19267103/301717 này . Nó cho phép phân chia một cam kết bằng cách sử dụnggit autorebase split COMMIT_ID
Jérôme Pouiller

Điều dễ nhất để làm mà không có rebase tương tác là (có thể) để tạo một nhánh mới bắt đầu từ cam kết trước khi bạn muốn tách, cherry-pick -n cam kết, đặt lại, stash, cam kết di chuyển tệp, áp dụng lại stash và cam kết các thay đổi và sau đó hợp nhất với chi nhánh cũ hoặc chọn các cam kết tiếp theo. (Sau đó chuyển tên chi nhánh cũ sang đầu hiện tại.) (Có lẽ tốt hơn nên làm theo lời khuyên của MBO và thực hiện một cuộc nổi loạn tương tác.) (Sao chép từ câu trả lời năm 2010 bên dưới)
William Pursell

1
Tôi gặp phải vấn đề này sau khi tôi vô tình đè bẹp hai xác nhận trong một cuộc nổi loạn trong một cam kết trước đó. Cách của tôi để sửa chữa nó là để kiểm tra các đè bẹp cam kết, git reset HEAD~, git stash, sau đó git cherry-picklà người đầu tiên cam kết trong bí, sau đó git stash pop. Trường hợp cherry-Lựa chọn của tôi là khá cụ thể ở đây, nhưng git stashgit stash popkhá tiện dụng cho người khác.
SOFe

Câu trả lời:


1799

git rebase -i sẽ làm điều đó.

Đầu tiên, bắt đầu với một thư mục làm việc sạch sẽ: git statussẽ không hiển thị các sửa đổi, xóa hoặc bổ sung đang chờ xử lý.

Bây giờ, bạn phải quyết định (các) cam kết nào bạn muốn chia.

A) Chia nhỏ cam kết gần đây nhất

Để phân tách cam kết gần đây nhất của bạn, trước tiên:

$ git reset HEAD~

Bây giờ cam kết các phần riêng lẻ theo cách thông thường, tạo ra nhiều cam kết như bạn cần.

B) Tách một cam kết xa hơn trở lại

Điều này đòi hỏi phải nổi loạn , nghĩa là viết lại lịch sử. Để tìm đúng cam kết, bạn có một số lựa chọn:

  • Nếu đó là ba lần quay lại, thì

    $ git rebase -i HEAD~3
    

    nơi 3là bao nhiêu cam kết sao nó được.

  • Nếu nó ở xa trên cây hơn bạn muốn đếm, thì

    $ git rebase -i 123abcd~
    

    nơi 123abcdlà SHA1 của cam kết mà bạn muốn chia tay.

  • Nếu bạn ở một nhánh khác (ví dụ: nhánh tính năng) mà bạn dự định hợp nhất thành chủ:

    $ git rebase -i master
    

Khi bạn nhận được màn hình chỉnh sửa rebase, hãy tìm cam kết bạn muốn tách ra. Ở đầu dòng đó, thay thế pickbằng edit( eviết tắt). Lưu bộ đệm và thoát. Rebase bây giờ sẽ dừng ngay sau khi cam kết bạn muốn chỉnh sửa. Sau đó:

$ git reset HEAD~

Cam kết các mảnh riêng lẻ theo cách thông thường, tạo ra nhiều cam kết như bạn cần, sau đó

$ git rebase --continue

2
Cảm ơn bạn cho câu trả lời này. Tôi muốn có một số tệp đã cam kết trước đó trong khu vực tổ chức, vì vậy các hướng dẫn cho tôi có một chút khác biệt. Trước khi tôi có thể git rebase --continue, tôi thực sự đã phải git add (files to be added), git committhì git stash(đối với các file còn lại). Sau đó git rebase --continue, tôi thường git checkout stash .lấy các tệp còn lại
Eric Hu

18
Câu trả lời của manojlds thực sự có liên kết này đến tài liệu về git-scm , điều này cũng giải thích quá trình phân chia cam kết rất rõ ràng.

56
Bạn cũng sẽ muốn tận dụng git add -pđể chỉ thêm một phần các tệp, có thể với etùy chọn chỉnh sửa diffs để chỉ cam kết một số hunk. git stashcũng hữu ích nếu bạn muốn thực hiện một số công việc về phía trước nhưng loại bỏ nó khỏi cam kết hiện tại.
Craig Ringer

2
Nếu bạn muốn phân tách sắp xếp lại các cam kết, điều tôi muốn làm là phân tách trước và sau đó sắp xếp lại riêng bằng cách sử dụng git rebase -i HEAD^3lệnh khác . Bằng cách này, nếu sự phân chia trở nên tồi tệ, bạn không phải hoàn tác quá nhiều công việc.
David M. Lloyd

4
@kralyk Các tập tin mới được cam kết trong HEAD sẽ được để lại trên đĩa sau git reset HEAD~. Họ không bị mất.
Wayne Conrad

312

Từ hướng dẫn sử dụng git-rebase (phần CAM KẾT)

Trong chế độ tương tác, bạn có thể đánh dấu các cam kết bằng hành động "chỉnh sửa". Tuy nhiên, điều này không nhất thiết có nghĩa là git rebase mong đợi kết quả của chỉnh sửa này chính xác là một cam kết. Thật vậy, bạn có thể hoàn tác cam kết hoặc bạn có thể thêm các cam kết khác. Điều này có thể được sử dụng để chia một cam kết thành hai:

  • Bắt đầu một rebase tương tác với git rebase -i <commit>^, đâu <commit>là cam kết bạn muốn chia. Trong thực tế, bất kỳ phạm vi cam kết nào cũng được, miễn là nó chứa cam kết đó.

  • Đánh dấu cam kết bạn muốn chia bằng hành động "chỉnh sửa".

  • Khi nói đến chỉnh sửa mà cam kết, thực hiện git reset HEAD^. Hiệu quả là ĐẦU được lặp lại bởi một, và chỉ số theo sau. Tuy nhiên, cây làm việc vẫn giữ nguyên.

  • Bây giờ thêm các thay đổi vào chỉ mục mà bạn muốn có trong lần xác nhận đầu tiên. Bạn có thể sử dụng git add(có thể tương tác) hoặc git gui(hoặc cả hai) để làm điều đó.

  • Cam kết chỉ mục hiện tại với bất kỳ thông điệp cam kết nào là phù hợp.

  • Lặp lại hai bước cuối cùng cho đến khi cây làm việc của bạn sạch sẽ.

  • Tiếp tục cuộc nổi loạn với git rebase --continue.


12
Trên Windows bạn có bạn sử dụng ~thay vì ^.
Kevin Kushot 18/07/2016

13
Lời cảnh báo: với cách tiếp cận này, tôi đã mất thông điệp cam kết.
user420667

11
@ user420667 Vâng, tất nhiên rồi. Chúng tôi đang resetcam kết, sau tất cả - bao gồm tin nhắn. Điều khôn ngoan cần làm, nếu bạn biết bạn sẽ chia tách một cam kết nhưng muốn giữ một số / tất cả tin nhắn của nó, là lấy một bản sao của tin nhắn đó. Vì vậy, git showcam kết trước khi rebaseing, hoặc nếu bạn quên hoặc thích điều này: quay lại với nó sau thông qua reflog. Không ai trong số họ thực sự sẽ bị "mất" cho đến khi nó được thu gom rác trong 2 tuần hoặc bất cứ điều gì.
gạch dưới

4
~^là những thứ khác nhau, ngay cả trên Windows. Bạn vẫn muốn có dấu mũ ^, vì vậy bạn sẽ chỉ cần thoát nó khi thích hợp với vỏ của bạn. Trong PowerShell, nó HEAD`^. Với cmd.exe, bạn có thể nhân đôi nó để thoát như thế nào HEAD^^. Trong hầu hết (tất cả?) Shell, bạn có thể bao quanh với dấu ngoặc kép như "HEAD^".
AndrewF

7
Bạn cũng có thể làm git commit --reuse-message=abcd123. Tùy chọn ngắn cho nó là -C.
j0057

41

Sử dụng git rebase --interactiveđể chỉnh sửa cam kết trước đó, chạy git reset HEAD~và sau đó git add -pđể thêm một số, sau đó thực hiện một cam kết, sau đó thêm một số và thực hiện một cam kết khác, bao nhiêu lần tùy thích. Khi bạn hoàn thành, hãy chạy git rebase --continuevà bạn sẽ có tất cả các cam kết phân chia trước đó trong ngăn xếp của bạn.

Quan trọng : Lưu ý rằng bạn có thể chơi xung quanh và thực hiện tất cả các thay đổi bạn muốn và không phải lo lắng về việc mất các thay đổi cũ, bởi vì bạn luôn có thể chạy git reflogđể tìm điểm trong dự án có chứa các thay đổi bạn muốn, (hãy gọi nó là a8c4ab) , và sau đó git reset a8c4ab.

Dưới đây là một loạt các lệnh để hiển thị cách thức hoạt động của nó:

mkdir git-test; cd git-test; git init

bây giờ thêm một tập tin A

vi A

thêm dòng này:

one

git commit -am one

sau đó thêm dòng này vào A:

two

git commit -am two

sau đó thêm dòng này vào A:

three

git commit -am three

bây giờ tập tin A trông như thế này:

one
two
three

và chúng tôi git logtrông giống như sau (tốt, tôi sử dụnggit log --pretty=oneline --pretty="%h %cn %cr ---- %s"

bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one

Hãy nói rằng chúng tôi muốn phân chia cam kết thứ hai , two.

git rebase --interactive HEAD~2

Điều này mang đến một thông điệp trông như thế này:

pick 2b613bc two
pick bfb8e46 three

Thay đổi đầu tiên pickthành một eđể chỉnh sửa cam kết đó.

git reset HEAD~

git diff cho chúng ta thấy rằng chúng ta chỉ chưa thực hiện cam kết mà chúng ta đã thực hiện cho lần xác nhận thứ hai:

diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two

Hãy để giai đoạn thay đổi và thêm "và một phần ba" vào dòng đó trong tệp A.

git add .

Đây thường là điểm trong một cuộc nổi loạn tương tác nơi chúng tôi sẽ chạy git rebase --continue, bởi vì chúng tôi thường chỉ muốn quay lại trong đống cam kết của mình để chỉnh sửa một cam kết trước đó. Nhưng lần này, chúng tôi muốn tạo một cam kết mới. Vì vậy, chúng tôi sẽ chạy git commit -am 'two and a third'. Bây giờ chúng tôi chỉnh sửa tập tin Avà thêm dòng two and two thirds.

git add . git commit -am 'two and two thirds' git rebase --continue

Chúng tôi có mâu thuẫn với cam kết của mình three, vì vậy hãy giải quyết nó:

Chúng tôi sẽ thay đổi

one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three

đến

one
two and a third
two and two thirds
three

git add .; git rebase --continue

Bây giờ chúng ta git log -ptrông như thế này:

commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:57:00 2013 -0700

    three

diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
 one
 two and a third
 two and two thirds
+three

commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:07:07 2013 -0700

    two and two thirds

diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
 one
 two and a third
+two and two thirds

commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:06:40 2013 -0700

    two and a third

diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two and a third

commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:56:40 2013 -0700

    one

diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one

38

Các câu trả lời trước đây đã đề cập đến việc sử dụng git rebase -iđể chỉnh sửa cam kết mà bạn muốn tách và cam kết thành từng phần.

Điều này hoạt động tốt khi chia các tệp thành các cam kết khác nhau, nhưng nếu bạn muốn tách các thay đổi thành các tệp riêng lẻ, bạn cần biết thêm.

Có được cam kết bạn muốn tách, sử dụng rebase -ivà đánh dấu nó edit, bạn có hai lựa chọn.

  1. Sau khi sử dụng git reset HEAD~, hãy xem qua các bản vá riêng lẻ bằng cách sử dụng các bản vá git add -pbạn muốn trong mỗi cam kết

  2. Chỉnh sửa bản sao làm việc để xóa những thay đổi bạn không muốn; cam kết trạng thái tạm thời đó; và sau đó kéo lại toàn bộ cam kết cho vòng tiếp theo.

Tùy chọn 2 hữu ích nếu bạn chia một cam kết lớn, vì nó cho phép bạn kiểm tra xem các phiên bản tạm thời có được xây dựng và chạy đúng như một phần của hợp nhất không. Điều này tiến hành như sau.

Sau khi sử dụng rebase -iediting cam kết, sử dụng

git reset --soft HEAD~

để hoàn tác cam kết, nhưng để lại các tệp đã cam kết trong chỉ mục. Bạn cũng có thể thực hiện thiết lập lại hỗn hợp bằng cách bỏ qua --soft, tùy thuộc vào mức độ gần với kết quả cuối cùng mà cam kết ban đầu của bạn sẽ diễn ra. Sự khác biệt duy nhất là liệu bạn có bắt đầu với tất cả các thay đổi được dàn dựng hay với tất cả các thay đổi không được tổ chức.

Bây giờ đi vào và chỉnh sửa mã. Bạn có thể xóa các thay đổi, xóa các tệp đã thêm và làm bất cứ điều gì bạn muốn để xây dựng cam kết đầu tiên của chuỗi bạn đang tìm kiếm. Bạn cũng có thể xây dựng nó, chạy nó và xác nhận rằng bạn có một bộ nguồn nhất quán.

Khi bạn hài lòng, hãy tạo giai đoạn / hủy kích hoạt các tệp khi cần (tôi muốn sử dụng git guicho việc này) và cam kết thay đổi thông qua UI hoặc dòng lệnh

git commit

Đó là cam kết đầu tiên được thực hiện. Bây giờ bạn muốn khôi phục bản sao làm việc của mình về trạng thái đã có sau khi cam kết bạn đang chia tách, để bạn có thể nhận thêm các thay đổi cho cam kết tiếp theo của mình. Để tìm sha1 của cam kết bạn đang chỉnh sửa, hãy sử dụng git status. Trong một vài dòng đầu tiên của trạng thái, bạn sẽ thấy lệnh rebase hiện đang thực thi, trong đó bạn có thể tìm thấy sha1 của cam kết ban đầu của mình:

$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
   pick 4847406 US135756: add debugging to the file download code
   e 65dfb6a US135756: write data and download from remote
  (see more in file .git/rebase-merge/done)
...

Trong trường hợp này, cam kết tôi đang chỉnh sửa có sha1 65dfb6a. Biết rằng, tôi có thể kiểm tra nội dung của cam kết đó trong thư mục làm việc của mình bằng cách sử dụng cả hình thức git checkoutcam kết và vị trí tệp. Ở đây tôi sử dụng .làm vị trí tệp để thay thế toàn bộ bản sao làm việc:

git checkout 65dfb6a .

Đừng bỏ lỡ dấu chấm ở cuối!

Điều này sẽ kiểm tra và giai đoạn, các tệp như sau cam kết bạn đang chỉnh sửa, nhưng liên quan đến cam kết trước đó bạn đã thực hiện, vì vậy mọi thay đổi bạn đã cam kết sẽ không phải là một phần của cam kết.

Bạn có thể tiếp tục ngay bây giờ và cam kết với tư cách là hoàn thành việc phân tách hoặc đi xung quanh một lần nữa, xóa một số phần của cam kết trước khi thực hiện một cam kết tạm thời khác.

Nếu bạn muốn sử dụng lại thông điệp cam kết ban đầu cho một hoặc nhiều cam kết, bạn có thể sử dụng nó trực tiếp từ các tệp đang hoạt động của rebase:

git commit --file .git/rebase-merge/message

Cuối cùng, một khi bạn đã cam kết tất cả các thay đổi,

git rebase --continue

sẽ tiếp tục và hoàn thành các hoạt động rebase.


3
Cảm ơn bạn!!! Đây phải là câu trả lời được chấp nhận. Sẽ tiết kiệm cho tôi rất nhiều thời gian và nỗi đau ngày hôm nay. Đó là câu trả lời duy nhất trong đó kết quả của cam kết cuối cùng đưa bạn đến trạng thái giống như cam kết được chỉnh sửa.
Doug Coburn

1
Tôi thích cách bạn sử dụng thông điệp cam kết ban đầu.
Salamandar

Sử dụng tùy chọn 2, khi tôi làm điều git checkout *Sha I'm Editing* .đó luôn luôn nói Updated 0 paths from *Some Sha That's Not In Git Log*và không có thay đổi.
Noumenon ngày

18

git rebase --interactivecó thể được sử dụng để phân chia một cam kết thành các cam kết nhỏ hơn. Các tài liệu Git về rebase có một hướng dẫn ngắn gọn về quy trình - Cam kết chia tách :

Trong chế độ tương tác, bạn có thể đánh dấu các cam kết bằng hành động "chỉnh sửa". Tuy nhiên, điều này không nhất thiết có nghĩa là git rebasemong đợi kết quả của chỉnh sửa này chính xác là một cam kết. Thật vậy, bạn có thể hoàn tác cam kết hoặc bạn có thể thêm các cam kết khác. Điều này có thể được sử dụng để chia một cam kết thành hai:

  • Bắt đầu một rebase tương tác với git rebase -i <commit>^, đâu <commit>là cam kết bạn muốn chia. Trong thực tế, bất kỳ phạm vi cam kết nào cũng được, miễn là nó chứa cam kết đó.

  • Đánh dấu cam kết bạn muốn chia bằng hành động "chỉnh sửa".

  • Khi nói đến chỉnh sửa mà cam kết, thực hiện git reset HEAD^. Hiệu quả là ĐẦU được lặp lại bởi một, và chỉ số theo sau. Tuy nhiên, cây làm việc vẫn giữ nguyên.

  • Bây giờ thêm các thay đổi vào chỉ mục mà bạn muốn có trong lần xác nhận đầu tiên. Bạn có thể sử dụng git add(có thể tương tác) hoặc git gui (hoặc cả hai) để làm điều đó.

  • Cam kết chỉ mục hiện tại với bất kỳ thông điệp cam kết nào là phù hợp.

  • Lặp lại hai bước cuối cùng cho đến khi cây làm việc của bạn sạch sẽ.

  • Tiếp tục cuộc nổi loạn với git rebase --continue.

Nếu bạn không hoàn toàn chắc chắn rằng các bản sửa đổi trung gian là nhất quán (chúng biên dịch, vượt qua bản kiểm tra, v.v.), bạn nên sử dụng git stashđể loại bỏ các thay đổi chưa được cam kết sau mỗi lần xác nhận, kiểm tra và sửa đổi cam kết nếu cần sửa chữa .


Trong Windows, hãy nhớ ^là một ký tự thoát cho dòng lệnh: nó sẽ được nhân đôi. Ví dụ, vấn đề git reset HEAD^^thay vì git reset HEAD^.
Frédéric

@ Frédéric: s Tôi chưa bao giờ gặp phải điều này. Ít nhất trong PowerShell đây không phải là trường hợp. Sau đó, sử dụng ^hai lần đặt lại hai lần xác nhận trên CHÍNH hiện tại.
Farway

@Farway, hãy thử nó trong một dòng lệnh cổ điển. PowerShell là một quái thú khác, nhân vật trốn thoát của nó là backtilt.
Frédéric

Để tóm tắt: "HEAD^"trong cmd.exe hoặc PowerShell, HEAD^^trong cmd.exe, HEAD`^trong PowerShell. Thật hữu ích khi tìm hiểu về cách các shell - và shell cụ thể của bạn - hoạt động (nghĩa là cách một lệnh biến thành các phần riêng lẻ được chuyển đến chương trình) để bạn có thể điều chỉnh các lệnh trực tuyến thành các ký tự phù hợp cho shell cụ thể của mình. (Không dành riêng cho Windows.)
AndrewF

11

Bây giờ trong TortoiseGit mới nhất trên Windows, bạn có thể làm điều đó rất dễ dàng.

Mở hộp thoại rebase, cấu hình nó và thực hiện các bước sau.

  • Nhấp chuột phải vào cam kết bạn muốn tách và chọn " Edit" (trong số các lựa chọn, xóa, xóa ...).
  • Nhấp vào " Start" để bắt đầu khởi động lại.
  • Khi nó đến cam kết phân tách, kiểm tra Edit/Splitnút "" và nhấp Amendtrực tiếp vào " ". Hộp thoại cam kết mở ra.
    Chỉnh sửa / Chia nhỏ cam kết
  • Bỏ chọn các tệp bạn muốn đặt vào một cam kết riêng.
  • Chỉnh sửa thông báo cam kết, sau đó bấm " commit".
  • Cho đến khi có các tệp để xác nhận, hộp thoại cam kết sẽ mở lại nhiều lần. Khi không còn tệp nào để cam kết, nó vẫn sẽ hỏi bạn nếu bạn muốn thêm một cam kết nữa.

Rất hữu ích, cảm ơn TortoiseGit!



8

Xin lưu ý rằng cũng có git reset --soft HEAD^. Nó tương tự git reset(mặc định là --mixed) nhưng nó vẫn giữ nguyên nội dung chỉ mục. Vì vậy, nếu bạn đã thêm / xóa tệp, bạn đã có chúng trong chỉ mục.

Hóa ra là rất hữu ích trong trường hợp cam kết khổng lồ.


3

Dưới đây là cách phân chia một cam kết trong IntelliJ IDEA , PyCharm , PhpStorm , v.v.

  1. Trong cửa sổ nhật ký Kiểm soát Phiên bản, chọn cam kết bạn muốn tách, nhấp chuột phải và chọn Interactively Rebase from Here

  2. đánh dấu cái bạn muốn chia thành edit, nhấp vàoStart Rebasing

  3. Bạn sẽ thấy một thẻ màu vàng được đặt có nghĩa là ĐẦU được đặt thành cam kết đó. Nhấp chuột phải vào cam kết đó, chọnUndo Commit

  4. Bây giờ những cam kết đó đã trở lại khu vực tổ chức, sau đó bạn có thể cam kết chúng một cách riêng biệt. Sau khi tất cả thay đổi đã được cam kết, cam kết cũ sẽ không hoạt động.


2

Điều dễ nhất để làm mà không có rebase tương tác là (có thể) để tạo một nhánh mới bắt đầu từ cam kết trước khi bạn muốn tách, cherry-pick -n cam kết, đặt lại, stash, cam kết di chuyển tệp, áp dụng lại stash và cam kết các thay đổi và sau đó hợp nhất với chi nhánh cũ hoặc chọn các cam kết tiếp theo. (Sau đó chuyển tên chi nhánh cũ sang đầu hiện tại.) (Có lẽ tốt hơn nên làm theo lời khuyên của MBO và thực hiện một cuộc nổi loạn tương tác.)


theo SO standarts những ngày này nên được coi là không trả lời; nhưng điều này vẫn có thể hữu ích cho những người khác, vì vậy nếu bạn không phiền hãy chuyển nó sang bình luận của bài viết gốc
YakovL

@YakovL Có vẻ hợp lý. Về nguyên tắc hành động tối thiểu, tôi sẽ không xóa câu trả lời, nhưng tôi sẽ không phản đối nếu có người khác làm.
William Pursell

điều này sẽ dễ dàng hơn nhiều so với tất cả các rebase -iđề xuất. Tôi nghĩ rằng điều này đã không nhận được nhiều sự chú ý do thiếu định dạng. Có lẽ bạn có thể xem lại, bây giờ bạn có 126k điểm và có thể biết cách SO. ;)
erikbwork


1

Nếu bạn có điều này:

A - B <- mybranch

Nơi bạn đã cam kết một số nội dung trong cam kết B:

/modules/a/file1
/modules/a/file2
/modules/b/file3
/modules/b/file4

Nhưng bạn muốn tách B thành C - D và nhận kết quả này:

A - C - D <-mybranch

Bạn có thể chia nội dung như thế này chẳng hạn (nội dung từ các thư mục khác nhau trong các cam kết khác nhau) ...

Đặt lại nhánh trở lại cam kết trước khi tách:

git checkout mybranch
git reset --hard A

Tạo cam kết đầu tiên (C):

git checkout B /modules/a
git add -u
git commit -m "content of /modules/a"

Tạo cam kết thứ hai (D):

git checkout B /modules/b
git add -u
git commit -m "content of /modules/b"

Điều gì nếu có các cam kết trên B?
CoolMind

1

Đã hơn 8 năm, nhưng có lẽ ai đó sẽ thấy nó hữu ích. Tôi đã có thể làm các thủ thuật mà không cần rebase -i. Ý tưởng là dẫn git đến trạng thái giống như trước khi bạn thực hiện git commit:

# first rewind back (mind the dot,
# though it can be any valid path,
# for instance if you want to apply only a subset of the commit)
git reset --hard <previous-commit> .

# apply the changes
git checkout <commit-you-want-to-split>

# we're almost there, but the changes are in the index at the moment,
# hence one more step (exactly as git gently suggests):
# (use "git reset HEAD <file>..." to unstage)
git reset

Sau này, bạn sẽ thấy điều này sáng bóng Unstaged changes after reset:và repo của bạn ở trạng thái như bạn sắp cam kết tất cả các tệp này. Từ bây giờ bạn có thể dễ dàng cam kết lại như bạn thường làm. Hy vọng nó giúp.


0

Một tài liệu tham khảo nhanh về các lệnh cần thiết, vì về cơ bản tôi biết phải làm gì nhưng luôn quên cú pháp đúng:

git rebase -i <sha1_before_split>
# mark the targeted commit with 'edit'
git reset HEAD^
git add ...
git commit -m "First part"
git add ...
git commit -m "Second part"
git rebase --continue

Tín dụng cho bài viết trên blog của Emmanuel Bernard .

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.