Kết hợp hai cam kết đầu tiên của kho Git?


197

Giả sử bạn có một lịch sử chứa ba lần xác nhận A, BC :

A-B-C

Tôi muốn kết hợp hai cam kết AB với một cam kết AB :

AB-C

Tôi đã thử

git rebase -i A

mở ra trình soạn thảo của tôi với các nội dung sau:

pick e97a17b B
pick asd314f C

Tôi thay đổi điều này thành

squash e97a17b B
pick asd314f C

Sau đó, Git 1.6.0.4 nói:

Cannot 'squash' without a previous commit

Có cách nào hay điều này là không thể?



Câu trả lời:


168

Sử dụng git rebase -i --root như phiên bản Git 1.7.12 .

Trong tệp rebase tương tác, thay đổi dòng cam kết B thứ hai thành squash và để lại các dòng khác khi chọn :

pick f4202da A
squash bea708e B
pick a8c6abc C

Điều này sẽ kết hợp hai cam kết AB với một cam kết AB .

Tìm thấy trong câu trả lời này .


126

Bạn đã thử:

git rebase -i A

Có thể bắt đầu như vậy nếu bạn tiếp tục editthay vì squash:

edit e97a17b B
pick asd314f C

sau đó chạy

git reset --soft HEAD^
git commit --amend
git rebase --continue

Làm xong.


4
Nếu bạn đang làm điều này để lặng lẽ sửa một github, bạn sẽ phải thêm "ban đầu" vào cam kết. ;-)
Bruno Bronosky

1
git rebase --abortđể bắt đầu lại và thực hiện đúng cách (không xóa bỏ cam kết đầu tiên trong trình chỉnh sửa)
oma

66

Alà cam kết ban đầu, nhưng bây giờ bạn muốn Blà cam kết ban đầu. Cam kết git là toàn bộ cây, không khác biệt ngay cả khi chúng thường được mô tả và xem theo các khác biệt mà chúng giới thiệu.

Công thức này hoạt động ngay cả khi có nhiều cam kết giữa A và B, và B và C.

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp

1
điều này kích hoạt một cuộc nổi loạn tương tác lớn khi tôi thực hiệngit rebase --onto tmp <sha1_for_B>
Alex

Xem xét tôi đã có một repo hoàn toàn mới chỉ với hai lần cam kết (mà tôi muốn cuộn thành một), điều này làm việc hoàn hảo với tôi. Cảm ơn bạn @CB Bailey
RominRonin

10

Trong trường hợp rebase tương tác, bạn phải thực hiện trước A để danh sách sẽ là:

pick A
pick B
pick C

để trở thành:

pick A
squash B
pick C

Nếu A là cam kết ban đầu, bạn phải có một cam kết ban đầu khác trước khi A. Git nghĩ về sự khác biệt, nó sẽ hoạt động dựa trên sự khác biệt giữa (A và B) và (B và C). Do đó squash không hoạt động trong ví dụ của bạn.


9

Trong trường hợp đó bạn có hàng trăm hoặc hàng ngàn cam kết, sử dụng câu trả lời kostmo của của

git rebase -i --root

có thể không thực tế và chậm, chỉ do số lượng lớn các cam kết mà tập lệnh rebase phải xử lý hai lần , một lần để tạo danh sách trình soạn thảo rebase tương tác (trong đó bạn chọn hành động nào cần thực hiện cho mỗi lần xác nhận) và một lần để thực hiện áp dụng lại các cam kết.

Dưới đây là một giải pháp thay thế sẽ tránh được chi phí thời gian tạo danh sách trình soạn thảo rebase tương tác bằng cách không sử dụng rebase tương tác ở vị trí đầu tiên. Theo cách này, nó tương tự như giải pháp của Charles Bailey . Bạn chỉ cần tạo một nhánh mồ côi từ lần xác nhận thứ hai, và sau đó khởi động lại tất cả các cam kết con cháu trên đầu nó:

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

Tài liệu



0

Lệnh Git cho đội hình: git rebase -i ĐẦU ~ [số lần xác nhận]

Hãy nói rằng bạn có lịch sử cam kết dưới đây:


chọn 5152061 feat: Đã thêm hỗ trợ để lưu ảnh. (A)
chọn 39c5a04 Fix: sửa lỗi. (B)
chọn 839c6b3 sửa: giải quyết xung đột. (C)

Bây giờ bạn muốn ép A và B thành AB, thực hiện các bước dưới đây:


chọn 5152061 feat: Đã thêm hỗ trợ để lưu ảnh. (A)
s 39c5a04 Fix: sửa lỗi. (B)
chọn 839c6b3 sửa: giải quyết xung đột. (C)

Lưu ý: đối với squash commit chúng ta có thể sử dụng squash hoặc s. Kết quả cuối cùng sẽ là:
chọn 5152061 feat: Đã thêm hỗ trợ để lưu ảnh. (AB)
chọn 839c6b3 sửa: giải quyết xung đột. (C)


-1

Bạn phải thực hiện một chút phép thuật dòng lệnh.

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

Điều đó sẽ để lại cho bạn một nhánh có AB và C là cam kết.


Bởi vì các cam kết ban đầu cũ và mới không có tổ tiên chung, bạn có thể gặp một số xung đột không cần thiết khi git cố gắng áp dụng toàn bộ lịch sử của chủ vào a, mặc dù chúng có một cây chung. Bằng cách sử dụng tùy chọn --onto để git rebase, bạn có thể cho git biết vị trí chính xác để bắt đầu áp dụng.
CB Bailey
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.