Git: Git brune
Lệnh git prune
là một tiện ích vệ sinh nội bộ mà dọn dẹp không thể truy cập hoặc "mồ côi" Git đối tượng. Các đối tượng không thể truy cập là những đối tượng không thể truy cập bởi bất kỳ ref nào. Bất kỳ cam kết nào không thể được truy cập thông qua một chi nhánh hoặc thẻ được coi là không thể truy cập. git prune
thường không được thực hiện trực tiếp. Prune được coi là lệnh thu gom rác và là lệnh con của lệnh git gc
.
Tổng quan về Git Prune
Để hiểu được các tác động của git prune
chúng ta cần mô phỏng một kịch bản trong đó một cam kết trở nên không thể truy cập được. Sau đây là một chuỗi các thực thi dòng lệnh sẽ mô phỏng trải nghiệm này.
~ $ cd git-prune-demo/
~/git-prune-demo $ git init .
Initialized empty Git repository in /Users/kev/Dropbox/git-prune-demo/.git/
~/git-prune-demo $ echo "hello git prune" > hello.txt
~/git-prune-demo $ git add hello.txt
~/git-prune-demo $ git commit -am "added hello.txt"
Chuỗi lệnh trước sẽ tạo ra một kho lưu trữ mới trong một thư mục có tên git-prune-demo
. Một cam kết bao gồm một tệp mới hello.text
được thêm vào repo với nội dung cơ bản là "xin chào git prune". Tiếp theo, chúng tôi sẽ tạo sửa đổi hello.txt
và tạo một cam kết mới từ những sửa đổi đó.
~/git-prune-demo $ echo "this is second line txt" >> hello.txt
~/git-prune-demo $ cat hello.txt
hello git prune
this is second line txt
~/git-prune-demo $ git commit -am "added another line to hello.txt"
[master 5178bec] added another line to hello.txt
1 file changed, 1 insertion(+)
Bây giờ chúng tôi có một lịch sử cam kết 2 trong repo demo này. Chúng tôi có thể xác minh bằng cách sử dụng git log
:
~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 14:49:59 2018 -0700
added another line to hello.txt
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 09:43:41 2018 -0700
added hello.txt
Đầu git log
ra hiển thị 2 cam kết và thông báo cam kết tương ứng về các chỉnh sửa được thực hiện hello.txt
. Bước tiếp theo là để chúng tôi thực hiện một trong những cam kết không thể truy cập được. Chúng tôi sẽ làm điều này bằng cách sử dụng git reset
lệnh. Chúng tôi đặt lại trạng thái của repo về cam kết đầu tiên. cam kết "đã thêm hello.txt".
~/git-prune-demo $ git reset --hard 994b122045cf4bf0b97139231b4dd52ea2643c7e
HEAD is now at 994b122 added hello.txt
Nếu bây giờ chúng ta sử dụng git log
để kiểm tra trạng thái của kho lưu trữ, chúng ta có thể thấy rằng chúng ta chỉ có một cam kết
~/git-prune-demo $ git log
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 09:43:41 2018 -0700
added hello.txt
Kho lưu trữ demo hiện ở trạng thái chứa một cam kết tách rời. Cam kết thứ hai mà chúng tôi đã thực hiện với thông báo "đã thêm một dòng khác vào hello.txt" không còn được hiển thị trong git log
đầu ra và hiện đã được tách ra. Có vẻ như chúng tôi đã mất hoặc xóa cam kết, nhưng Git rất nghiêm ngặt về việc không xóa lịch sử. Chúng tôi có thể xác nhận nó vẫn có sẵn, nhưng tách ra, bằng cách sử dụng git checkout
để truy cập trực tiếp:
~/git-prune-demo $ git checkout 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Note: checking out '5178becc2ca965e1728554ce1cb8de2f2c2370b1'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at 5178bec... added another line to hello.txt
~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 14:49:59 2018 -0700
added another line to hello.txt
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date: Sun Sep 30 09:43:41 2018 -0700
added hello.txt
Khi chúng tôi kiểm tra cam kết tách ra, Git đủ chu đáo để cung cấp cho chúng tôi một thông điệp chi tiết giải thích rằng chúng tôi đang ở trong trạng thái tách rời. Nếu chúng ta kiểm tra nhật ký ở đây, chúng ta có thể thấy rằng cam kết "đã thêm một dòng khác vào hello.txt" hiện đã quay trở lại trong đầu ra nhật ký! Bây giờ chúng ta biết kho lưu trữ ở trạng thái mô phỏng tốt với một cam kết tách rời mà chúng ta có thể thực hành sử dụng git prune
. Trước tiên, chúng ta hãy trở lại master
chi nhánh bằng cách sử dụnggit checkout
~/git-prune-demo $ git checkout master
Warning: you are leaving 1 commit behind, not connected to
any of your branches:
5178bec added another line to hello.txt
If you want to keep it by creating a new branch, this may be a good time
to do so with:
git branch <new-branch-name> 5178bec
Switched to branch 'master'
Khi trở về với chủ nhân thông qua git checkout
, Git một lần nữa đủ chu đáo để cho chúng tôi biết rằng chúng tôi đang để lại một cam kết tách rời phía sau. Bây giờ là lúc để cắt tỉa các cam kết tách ra! Tiếp theo, chúng tôi sẽ thực thi git prune
nhưng chúng tôi phải chắc chắn chuyển một số tùy chọn cho nó. --dry-run
và --verbose
sẽ hiển thị đầu ra cho biết những gì được thiết lập để được cắt tỉa nhưng không thực sự cắt tỉa nó.
~/git-prune-demo $ git prune --dry-run --verbose
Lệnh này rất có thể sẽ trả về đầu ra trống. Đầu ra trống rỗng ngụ ý rằng prune sẽ không thực sự xóa bất cứ điều gì. Tại sao điều này sẽ xảy ra? Vâng, cam kết rất có thể không tách ra hoàn toàn. Ở đâu đó Git vẫn đang duy trì một tài liệu tham khảo về nó. Đây là một ví dụ điển hình về lý do tại sao git prune
không được sử dụng độc lập bên ngoài git gc
. Đây cũng là một ví dụ điển hình về việc khó có thể mất hoàn toàn dữ liệu với Git.
Rất có thể Git đang lưu trữ một tham chiếu đến cam kết tách rời của chúng tôi trong reflog. Chúng tôi có thể điều tra bằng cách chạy git reflog
. Bạn sẽ thấy một số kết quả mô tả chuỗi các hành động chúng tôi đã thực hiện để đến đây. Để biết thêm thông tin về việc git reflog
truy cập git reflog
trang. Ngoài việc lưu giữ lịch sử trong reflog, Git có ngày hết hạn nội bộ khi nó sẽ cắt tỉa các cam kết tách ra. Một lần nữa, đây là tất cả các chi tiết thực hiện git gc
xử lý và git prune
không nên được sử dụng độc lập.
Để kết thúc git prune
bản demo mô phỏng của chúng tôi, chúng tôi phải xóa reflog
~/git-prune-demo $ git reflog expire --expire=now --expire-unreachable=now --all
Lệnh trên sẽ buộc hết hạn tất cả các mục vào reflog cũ hơn bây giờ. Đây là một lệnh tàn bạo và nguy hiểm mà bạn không bao giờ phải sử dụng như người dùng Git thông thường. Chúng tôi đang thực hiện lệnh này để chứng minh một thành công git prune
. Với việc reflog hoàn toàn bị xóa sạch, bây giờ chúng ta có thể thực thi git prune
.
~/git-prune-demo $ git prune --dry-run --verbose --expire=now
1782293bdfac16b5408420c5cb0c9a22ddbdd985 blob
5178becc2ca965e1728554ce1cb8de2f2c2370b1 commit
a1b3b83440d2aa956ad6482535cbd121510a3280 commit
f91c3433eae245767b9cd5bdb46cd127ed38df26 tree
Lệnh này sẽ xuất ra một danh sách các tham chiếu đối tượng Git SHA trông giống như ở trên.
Sử dụng
git prune
có một danh sách ngắn các tùy chọn mà chúng tôi đề cập trong phần tổng quan.
-n --dry-run
Đừng thực hiện cắt tỉa. Chỉ cần hiển thị một đầu ra của những gì nó sẽ làm
-v --verbose
Hiển thị đầu ra của tất cả các đối tượng và hành động được thực hiện bởi prune
--progress
Hiển thị đầu ra cho biết tiến trình của mận
--expire <time>
Buộc hết hạn các đối tượng đã qua <time>
<head>…
Chỉ định một <head>
sẽ duy trì bất kỳ tùy chọn từ ref đó
Thảo luận
Sự khác biệt giữa Git Prune, Git Fetch --prune và Git Remote Prune là gì?
git remote prune
và git fetch --prune
làm điều tương tự: xóa các ref cho các nhánh không tồn tại trên remote. Điều này rất mong muốn khi làm việc trong một quy trình làm việc nhóm trong đó các nhánh từ xa bị xóa sau khi hợp nhất master
. Lệnh thứ hai, git fetch --prune
sẽ kết nối với điều khiển từ xa và tìm nạp trạng thái từ xa mới nhất trước khi cắt tỉa. Nó thực chất là sự kết hợp của các lệnh:
git fetch --all && git remote prune
Lệnh chung git prune
là hoàn toàn khác nhau. Như đã thảo luận trong phần tổng quan, git prune sẽ xóa các xác nhận tách rời cục bộ.
Làm thế nào để tôi làm sạch các chi nhánh lỗi thời?
git fetch --prune
là tiện ích tốt nhất để làm sạch các chi nhánh lỗi thời. Nó sẽ kết nối với một kho lưu trữ từ xa được chia sẻ từ xa và tìm nạp tất cả các ref chi nhánh từ xa. Sau đó nó sẽ xóa các ref từ xa không còn được sử dụng trên kho lưu trữ từ xa.
Git Remote Prune Origin có xóa Chi nhánh địa phương không?
Không git remote prune origin
sẽ chỉ xóa các ref cho các nhánh từ xa không còn tồn tại. Git lưu trữ cả refs địa phương và từ xa. Một kho lưu trữ sẽ có local/origin
và remote/origin
bộ sưu tập ref. git remote prune origin
sẽ chỉ cắt tỉa các ref trong remote/origin
. Điều này an toàn để lại công việc địa phương trong local/origin
.
Tóm tắt Git Prune
Các git prune
lệnh được thiết kế để được viện dẫn như một lệnh đứa trẻ git gc
. Rất khó có khả năng bạn sẽ cần phải gọi git prune
năng lực kỹ thuật phần mềm hàng ngày. Các lệnh khác là cần thiết để hiểu tác dụng của git prune
. Một số lệnh sử dụng trong bài viết này là git log
, git reflog
, và git checkout
.