Làm thế nào để loại bỏ các cam kết đầu tiên trong git?


179

Tôi tò mò về cách loại bỏ cam kết đầu tiên trong git.

Sửa đổi trước khi cam kết bất kỳ điều gì là gì? Bản sửa đổi này có tên hoặc thẻ không?


2
Để bắt đầu với git, bạn nên biết rằng sửa đổi là vô nghĩa. Bạn có thể nói về các cam kết hoặc SHA tương đối của họ. Ngoài ra, tại sao bạn muốn làm điều này? Cam kết đầu tiên là những gì mọi thứ được xây dựng trên. Bạn có thể xóa một vài lần xác nhận cùng nhau, bao gồm cả lần xác nhận đầu tiên, trở thành lần xác nhận đầu tiên mới, nhưng việc xóa cam kết đầu tiên (hoặc xóa bất kỳ cam kết cuối cùng nào) có nghĩa là gì?
Shahbaz

@Shahbaz yeah, thats cách tốt nhất, hãy nhìn vào đây để dụ: ariejan.net/2011/07/05/git-squash-your-latests-commits-into-one
timaschew

5
Bạn có thể sử dụng git rebase -i --root. Xem câu trả lời SO sau đây để biết chi tiết: stackoverflow.com/questions/2246208/ từ
MKroehnert


Câu trả lời này có giải pháp chính xác để xóa cam kết gốc của nhánh hiện tại:git filter-branch --parent-filter "sed 's/-p <the_commit>//'" HEAD
Jody Bruchon

Câu trả lời:


319

Đối với tôi, cách an toàn nhất là sử dụng update-reflệnh:

git update-ref -d HEAD

Nó sẽ xóa tham chiếu được đặt tên HEAD, vì vậy nó sẽ thiết lập lại (nhẹ nhàng, bạn sẽ không mất công việc của bạn) tất cả các cam kết của chi nhánh hiện tại của bạn .

Nếu điều bạn muốn là hợp nhất cam kết đầu tiên với lần thứ hai, bạn có thể sử dụng rebaselệnh:

git rebase -i --root

Cách cuối cùng có thể là tạo một nhánh mồ côi, một nhánh có cùng nội dung nhưng không có bất kỳ lịch sử cam kết nào và cam kết nội dung mới của bạn trên đó:

git checkout --orphan <new-branch-name>

7
Thật tệ khi đây không phải là câu trả lời được chấp nhận. Cũng thật tệ khi hầu hết các lượt truy cập trên google ít nhiều nói rằng "bạn không thể hoàn tác cam kết đầu tiên". Điều này đã lừa tôi. Cảm ơn!
danielpops

1
Cảm ơn @danielpops đã hỗ trợ bạn! Thật tốt khi nhận thấy rằng tôi đã trả lời câu hỏi này 3 năm sau. Git đã phát triển trong thời gian đó.
tzi

Tôi đã sử dụng rebase, đánh dấu lần xác nhận thứ hai là "squash", và sau đó thực hiện một cú hích - lực đẩy về nguồn gốc. Cảm ơn!
Philip Atz

1
git update-ref -d HEAD là cách an toàn nhất để xóa tất cả lịch sử, không chỉ là cam kết ban đầu.
dùng1767316

Tôi đã làm điều đó và nó đã xóa tất cả các tập tin của tôi mà tôi đã thêm vào cam kết đầu tiên. Buồn. Ít nhất thì nó cũng không nhiều
Vyacheslav Tsivina

42

Không có gì trước lần cam kết đầu tiên, vì mọi cam kết đều đề cập đến một cam kết cha mẹ. Điều này làm cho cam kết đầu tiên trở nên đặc biệt (một cam kết mồ côi), vì vậy không có cách nào để đề cập đến một "trạng thái" trước đó.

Vì vậy, nếu bạn muốn sửa lỗi cam kết, bạn có thể chỉ cần git commit --amend: điều này sẽ sửa đổi cam kết mà không tạo ra một cam kết khác.

Nếu bạn chỉ muốn bắt đầu lại, hãy xóa .gitkho lưu trữ và tạo một kho khác vớigit init


7
Câu trả lời này không chính xác: có một cách để trở lại trạng thái trước khi cam kết đầu tiên. Xem câu trả lời của tzi dưới đây.
David Nelson

2
Các --amendcũng sẽ không cập nhật tác giả đúng cách nếu nó ban đầu được cấu hình sai. Đó là những gì tôi cần vì vậy tôi đã sử dụng câu trả lời được chấp nhận và sau đó chỉ cần thực hiện một cam kết mới.
Đánh dấu Edington

11
# Check out to a temporary branch:
git checkout --orphan TEMP_BRANCH

# Add all the files:
git add -A

# Commit the changes:
git commit -am "Initial commit"

# Delete the old branch:
git branch -D master

# Rename the temporary branch to master:
git branch -m master

# Finally, force update to our repository:
git push -f origin master

3
Không phải là một câu trả lời: Câu hỏi là "làm thế nào để loại bỏ cam kết đầu tiên" chứ không phải "làm thế nào để xóa mọi thứ trừ lần cam kết cuối cùng".
peterh - Phục hồi Monica

1
Tôi đã tìm kiếm chính xác cho điều này. Cảm ơn!
Krzysztof Tomaszewski

6

Bạn có thể chỉ muốn chỉnh sửa cam kết đầu tiên của mình (vì luôn có một cam kết đầu tiên trong repo git). Cân nhắc sử dụng git commit --amend --reset-authorthay vì thông thường git commit --amend.


1
Không phải là một câu trả lời: câu hỏi muốn xóa cam kết đầu tiên và không sửa đổi các thuộc tính của lần cuối cùng.
peterh - Phục hồi Monica

@ peterh-ReinstateMonica Để làm rõ: Các cam kết có thể được sửa đổi trong quá trình rebase tương tác để thay đổi hoàn toàn nội dung của chúng, nhưng --reset-tác giả cũng cần được cung cấp để thay đổi tác giả. Cùng với đó, bạn hoàn toàn có thể thay thế cam kết đầu tiên theo ý thích của mình. Xem thêm câu trả lời của CharlesB.
Max Beikirch

3

Tôi đang tìm cách hoàn tác tất cả các cam kết git từ một repo, giống như chúng chưa từng xảy ra.

Rebasing sẽ làm việc đến một điểm. Tuy nhiên, lần đầu tiên (theo cam kết git lâu đời nhất) sẽ luôn có vấn đề, vì nó không có cha mẹ, do đó sẽ xảy ra lỗi.

Không có câu trả lời nào trong số này trả lời cho tôi. Nhưng sau rất nhiều lần tìm kiếm và dùng thử, tôi thấy điều này có hiệu quả!

git update-ref -d HEAD
git push origin master -f

Hy vọng điều này sẽ giúp bạn. Có một ngày tuyệt vời.


1
Để rõ ràng cho bất cứ ai đọc câu trả lời này: điều này xóa mọi cam kết, nhưng OP chỉ muốn xóa cam kết đầu tiên được thực hiện cho một repo; không chạy cái này để xóa lần xác nhận đầu tiên vì nó sẽ xóa TẤT CẢ các lần xác nhận.
Jody Bruchon

2

Một cách khác bạn có thể làm là:

  1. Thanh toán cho một chi nhánh bạn muốn giữ (nói dev) git checkout dev
  2. Bây giờ, xóa chi nhánh bạn muốn đặt lại git branch -D master
  3. Bây giờ, tạo một nhánh trống có cùng tên git checkout --orphan master

Tất nhiên, tất cả điều này sẽ phụ thuộc vào usecase của bạn, nhưng nếu bạn có nhiều hơn một nhánh, việc xóa .gitthư mục sẽ không có ý nghĩa.


3
Sau khi làm điều này, bạn phải xóa chi nhánh trong điều khiển từ xa trước khi đẩy. Nếu không, khi cố gắng đẩy bạn sẽ gặp lỗi này :! [bị từ chối] master -> master (không chuyển tiếp nhanh) - lỗi: không thể đẩy một số ref đến 'git@github.com: r1 / r2.git' - gợi ý: Cập nhật bị từ chối vì mẹo của chi nhánh hiện tại của bạn là phía sau - gợi ý: đối tác từ xa của nó. Tích hợp các thay đổi từ xa (ví dụ: gợi ý: 'git pull ...') trước khi đẩy lại ... - Nếu bạn thực hiện thao tác git, tất cả các cam kết sẽ quay trở lại.
dxvargas

2

Nếu bạn muốn giữ các nhánh khác, nhưng ví dụ, làm cho masternhánh bắt đầu lại mà không có lịch sử chung cho các nhánh khác, một cách an toàn để đạt được điều này là tạo một kho lưu trữ mới và đẩy nội dung của nó trong kho cũ của bạn:

cd ..
git init newrepo
cd newrepo
# make some initial commits
git push ../oldrepo master:newmaster

Điều này tạo ra newmasternhánh trong kho lưu trữ cũ, với lịch sử không phổ biến với bất kỳ nhánh nào khác. Tất nhiên, bạn chỉ có thể ghi đè lên master, với git push -f.

Nếu bạn muốn hủy tất cả các nhánh và tất cả nội dung hiện có, thì hãy chạy

rm -rf .git/

1
Không phải là một câu trả lời: OP muốn xóa cam kết đầu tiên và không bắt đầu một repo git mới với cây làm việc hiện tại như cam kết ban đầu.
peterh - Phục hồi Monica

@peterh Tôi đồng ý git rebase --rootcó lẽ là điều OP muốn, nhưng xem xét câu trả lời này có hai điểm nâng cao, tôi sẽ không xóa nó trong trường hợp ai đó vẫn thấy nó có liên quan.
user1338062

Tôi nghĩ rằng câu trả lời này là chính xác liên quan - nếu bạn muốn xóa các cam kết đầu tiên tại một số chi nhánh, và có chỉ có một cam kết! (Nhưng bạn cũng muốn giữ các cam kết khác trong các nhánh khác; và bạn cũng muốn thực hiện điều này để các thay đổi kết thúc bằng Bitbucket hoặc Github, không chỉ cục bộ.) Tôi tin rằng câu trả lời này là một cách để làm điều này, và Tôi nghĩ rằng nó có thể là cách duy nhất ở đây để làm điều này. (Đó là bởi vì - cũng như tôi có thể thấy - không có cách nào để buộc một chi nhánh địa phương không có cam kết với một chi nhánh ở xa với một số cam kết.)
MikeBeaton

0

Nếu bạn vừa cam kết nhưng không đẩy nó thì chỉ cần xóa thư mục .gitgit initmột lần nữa ...


@peterh Có chứ. Bạn đang giả định (tôi nghĩ) rằng câu hỏi của OP là về việc muốn xóa cam kết đầu tiên nhưng giữ các cam kết tiếp theo. Một khả năng khác (mà tôi nghĩ hoàn toàn phù hợp với câu hỏi của OP - và câu trả lời này là câu trả lời) là muốn xóa cam kết đầu tiên và duy nhất từ ​​một chi nhánh, đưa nó trở lại hoàn toàn trống rỗng.
MikeBeaton

@MikeBeaton Bạn nói đúng. Tôi xóa bình luận của mình, nhưng sau đó tôi cần bỏ phiếu để đóng câu hỏi không rõ ràng. Lưu ý, mặc dù chỉ tôi mới đưa ra nhận xét này, nhưng đằng sau tôi có 40000 khách truy cập và một phần quan trọng trong số họ đã tìm thấy câu hỏi này với google - và họ không nhận được những gì họ muốn.
peterh - Tái lập Monica

Điều đó có vẻ cực đoan. Xóa câu hỏi? Có thể không (hoàn toàn tốt) có thể lập luận rằng một câu trả lời đầy đủ cho câu hỏi hoàn toàn hợp lý là có hai cách tiếp cận khác nhau cần được thực hiện, tùy thuộc vào việc ... vv? (Ý tôi là, tôi, vì một, muốn biết cách loại bỏ cam kết đầu tiên khi đó không phải là cam kết duy nhất và cũng là cách xóa cam kết đầu tiên khi đó cam kết duy nhất. Điều đó chắc chắn không rõ ràng và chắc chắn phụ thuộc về chi tiết cụ thể khi thực hiện, thực tế hóa ra cần có những cách tiếp cận thực sự khác nhau trong từng trường hợp.)
MikeBeaton

0

Câu trả lời cho câu hỏi phụ thuộc vào việc:

  • Bạn muốn xóa cam kết VÀ CHỈ đầu tiên trên một nhánh (trong khi để các nhánh khác như cũ), hoặc liệu

  • Bạn muốn xóa cam kết đầu tiên trên một số chi nhánh, trong khi 'rời khỏi vị trí' các cam kết tiếp theo (và các chi nhánh khác).

Thứ hai trong số này là tương đối đơn giản. Về cơ bản, bạn phải truy cập vào root - hầu hết các câu trả lời ở đây là về các cách để làm điều này.

Để thực hiện lần thứ hai (loại bỏ cam kết đầu tiên và duy nhất khỏi một nhánh trong khi để các nhánh khác một mình) thì khó hơn. Hoặc, ít nhất, đặc biệt khó hơn nếu bạn muốn nó xảy ra và để thay đổi được phản ánh lại trong GitHub hoặc Bitbucket. Có (theo như tôi có thể nói) không có cách nào trong Git để đẩy hoặc buộc đẩy một nhánh không có cam kết. Và cũng có (một lần nữa, theo như tôi có thể thấy) không có cách nào để tạo ra một nhánh mới, trống rỗng, không có cam kết nào trong GitHub hoặc Bitbucket. Vì vậy, về cơ bản bạn phải tạo một kho lưu trữ mới để tạo một nhánh hoàn toàn trống, sau đó thêm lại các nhánh mà bạn muốn (bao gồm các cam kết mà bạn muốn) - theo câu trả lời của @ user1338062.

Vì vậy, tôi hy vọng câu trả lời này làm rõ những gì có thể không rõ ràng - rằng có hai cách tiếp cận khác nhau cần được thực hiện, cho hai kịch bản khác nhau (ít nhiều hợp lý), đó là cả hai điều bạn có thể muốn làm, theo thứ tự để hoàn toàn làm chủ những gì OP yêu cầu.

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.