Làm thế nào để bạn stash một tập tin không bị theo dõi?


1437

Tôi có các thay đổi đối với một tệp, cộng với một tệp mới và muốn sử dụng git stash để loại bỏ chúng trong khi tôi chuyển sang một tác vụ khác. Nhưng git stash tự nó chỉ chứa các thay đổi đối với tệp hiện có; tập tin mới vẫn còn trong cây làm việc của tôi, làm xáo trộn công việc tương lai của tôi. Làm thế nào để tôi bỏ tập tin không bị theo dõi này?


27
Xin lưu ý rằng nếu bạn chỉ có các tệp chưa được bẻ khóa trong ngăn chứa của mình, nó sẽ trông giống như một tệp trống, vì trong khi git stash showtrả về không có gì và bạn có thể bị bỏ rơi nó (như tôi đã làm trong khi nó chứa một tập lệnh hữu ích tôi đã viết cách đây vài tháng → cách phục hồi stash bị rơi )
Maxime R.

Câu trả lời:


1925

Để bỏ thư mục làm việc của bạn bao gồm các tệp không bị theo dõi (đặc biệt là các tệp trong .gitignore) thì có lẽ bạn muốn sử dụng cmd này:

git stash --include-untracked

Thêm chi tiết:

Cập nhật ngày 17 tháng 5 năm 2018:

Các phiên bản mới của git hiện có git stash --alltất cả các tệp, bao gồm các tệp không bị theo dõi và bị bỏ qua.
git stash --include-untrackedkhông còn chạm vào các tệp bị bỏ qua (đã thử nghiệm trên git 2.16.2).

Câu trả lời gốc dưới đây:

Cảnh báo, làm điều này sẽ xóa vĩnh viễn các tệp của bạn nếu bạn có bất kỳ thư mục / * mục nào trong tệp gitignore của bạn.

Kể từ phiên bản 1.7.7, bạn có thể sử dụng git stash --include-untrackedhoặc git stash save -ubỏ các tệp không bị theo dõi mà không cần sắp xếp chúng.

Thêm ( git add) tệp và bắt đầu theo dõi nó. Sau đó đâm vào. Vì toàn bộ nội dung của tệp là mới, chúng sẽ được lưu trữ và bạn có thể thao tác nó khi cần thiết.


4
Tại sao stash vẫn stash thay đổi các tệp hiện có mặc dù những thay đổi đó chưa được tổ chức?
Alan Christensen

6
@ alan-christensen Đọc MÔ TẢ nhân kernel.org/pub/software/scm/git/docs/git-stash.html . Vấn đề là có một cây làm việc sạch sẽ sau khi đâm.
Kelvin

3
@Kelvin điều tôi muốn nói trong nhận xét của tôi là nó không chứa các tệp mới trừ khi chúng được dàn dựng tuy nhiên nó không chứa các tệp hiện có ngay cả khi chúng chưa được dàn dựng. Có vẻ không phù hợp với tôi.
Alan Christensen

11
@AlanChristensen quan điểm là bỏ đi những thứ có thể bị ghi đè bằng cách thanh toán của một chi nhánh khác.
JWG

3
Khi bạn có câu trả lời hàng đầu ở đây, tôi sẽ yêu cầu bạn liệt kê git stash --include-untrackedtrước git stash --alltrong câu trả lời của bạn vì hai lý do. Đầu tiên, nó trả lời câu hỏi của OP tốt hơn vào năm 2019 và thứ hai bởi vì - tất cả đều làm điều mà hầu hết người dùng có thể không muốn ở chỗ nó xóa tất cả các tệp .gitignored
Daniel Flippance

411

Kể từ git 1.7.7, git stashchấp nhận --include-untrackedtùy chọn (hoặc viết tắt -u). Để bao gồm các tệp không bị theo dõi trong ngăn chứa của bạn, hãy sử dụng một trong các lệnh sau:

git stash --include-untracked
git stash -u

Cảnh báo, làm điều này sẽ xóa vĩnh viễn các tệp của bạn nếu bạn có bất kỳ thư mục / * mục nào trong tệp gitignore của bạn.


15
Thật tuyệt - cuối cùng nó cũng hoạt động như được mô tả trong trang hướng dẫn. Không stashing (và làm sạch) các tập tin mới là hành vi bị hỏng.
Steve Bennett

1
phiên bản git của tôi là 1.9.1 và ngay cả khi những gì tôi có .gitignoretrông như thế này ignoredDirectoryvà không phải ignoredDirectory/*nó vẫn xóa những thứ không được theo dõi. Ngay cả các tập tin không bị theo dõi không chỉ thư mục.
theUn Unknown777

22
Bạn có thể vui lòng giải thích cảnh báo? Tại sao nó sẽ xóa những tập tin đó? Nó có xóa chúng và không stash chúng? Tôi đã sử dụng Git một thời gian và không gặp phải vấn đề này.
Alexanderr Dubinsky

Có cảnh báo áp dụng cho *.extensioncác mục là tốt?
arekolek

3
@ aleksandr-dubinsky, tùy chọn @arekolek - git1.8.3 -u( --include-untracked) có thể stash và bật các tệp không bị theo dõi ổn nhưng git stash showkhông liệt kê các tệp không được theo dõi trong stash
xilef

77

Thêm tệp vào chỉ mục:

git add path/to/untracked-file
git stash

Toàn bộ nội dung của chỉ mục, cộng với bất kỳ thay đổi chưa được xử lý nào đối với các tệp hiện có, tất cả sẽ khiến nó bị bỏ lại.


Điều gì xảy ra nếu bạn không muốn xóa các thay đổi đã có trong chỉ mục? Là stashing các tập tin mới vẫn có thể?
allyourcode

Cam kết chỉ mục, bỏ tệp mới, sau đó hoàn nguyên cam kết và / hoặc kiểm tra các tệp từ cam kết. Đó là một giải pháp bùn, nhưng nó sẽ hoạt động.
Gdalya

git add .không xem xét nó vì một số lý do
TheBilTheory

53

Trong git bash, việc lấy các tệp không bị theo dõi được thực hiện bằng cách sử dụng lệnh

git stash --include-untracked

hoặc là

git stash -u

http://git-scm.com/docs/git-stash

git stash loại bỏ bất kỳ tập tin chưa được theo dõi hoặc không được kiểm duyệt khỏi không gian làm việc của bạn. Và bạn có thể hoàn nguyên git stash bằng cách sử dụng các lệnh sau

git stash pop

Điều này sẽ đặt các tập tin trở lại trong không gian làm việc địa phương của bạn.

Kinh nghiệm của tôi

Tôi đã phải thực hiện sửa đổi tệp gitIgnore của mình để tránh di chuyển các tệp. Classpath và .project vào repo từ xa. Tôi không được phép di chuyển .gitIgnore đã sửa đổi này trong repo từ xa.

Các tập tin. classpath và .project rất quan trọng đối với nhật thực - đó là trình soạn thảo java của tôi.

Trước hết tôi đã chọn lọc thêm phần còn lại của mình vào các tệp và cam kết dàn dựng. Tuy nhiên, lần đẩy cuối cùng không thể được thực hiện trừ khi các tệp .gitIgnore được sửa đổi và các tệp không được theo dõi viz. .project và. classpath không được lưu.

Tôi đã sử dụng

 git stash 

để lấy tệp .gitIgnore đã sửa đổi.

Để lưu tập tin. Classpath và .project, tôi đã sử dụng

git stash --include-untracked

và nó loại bỏ các tập tin từ không gian làm việc của tôi. Sự vắng mặt của những tập tin này làm mất khả năng làm việc của tôi trên vị trí làm việc của tôi trong nhật thực. Tôi đã tiến hành hoàn thành thủ tục đẩy các tập tin đã cam kết vào điều khiển từ xa. Một khi điều này được thực hiện thành công, tôi đã sử dụng

git stash pop

Điều này dán các tập tin tương tự trở lại trong không gian làm việc của tôi. Điều này đã mang lại cho tôi khả năng của tôi để làm việc trong cùng một dự án trong nhật thực. Hy vọng bàn chải này bỏ qua những quan niệm sai lầm.


2
Tại sao bạn không sử dụng gitignore toàn cầu cho các tệp IDE? I E. sử dụng ~/.gitignore.
Antti Pihlaja

20

Như đã nói ở nơi khác, câu trả lời là git addtập tin. ví dụ:

git add path/to/untracked-file
git stash

Tuy nhiên, câu hỏi cũng được nêu ra trong một câu trả lời khác: Điều gì xảy ra nếu bạn không thực sự muốn thêm tệp? Vâng, như tôi có thể nói, bạn phải. Và sau đây sẽ KHÔNG hoạt động:

git add -N path/to/untracked/file     # note: -N is short for --intent-to-add
git stash

Điều này sẽ thất bại, như sau:

path/to/untracked-file: not added yet
fatal: git-write-tree: error building trees
Cannot save the current index state

Vậy, bạn có thể làm gì? Chà, bạn phải thực sự thêm tệp, tuy nhiên , bạn thực sự có thể hủy thêm nó sau, với git rm --cached:

git add path/to/untracked-file
git stash save "don't forget to un-add path/to/untracked-file" # stash w/reminder
# do some other work
git stash list
# shows:
# stash@{0}: On master: don't forget to un-add path/to/untracked-file
git stash pop   # or apply instead of pop, to keep the stash available
git rm --cached path/to/untracked-file

Và sau đó bạn có thể tiếp tục làm việc, ở trạng thái giống như trước đây git add(cụ thể là với một tệp chưa được mã hóa được gọi path/to/untracked-file; cộng với bất kỳ thay đổi nào khác mà bạn có thể phải theo dõi các tệp).

Một khả năng khác cho quy trình làm việc về điều này sẽ là một cái gì đó như:

git ls-files -o > files-to-untrack
git add `cat files-to-untrack` # note: files-to-untrack will be listed, itself!
git stash
# do some work
git stash pop
git rm --cached `cat files-to-untrack`
rm files-to-untrack

[Lưu ý: Như đã đề cập trong một nhận xét từ @mancocapac, bạn có thể muốn thêm --exclude-standardvào git ls-fileslệnh (vì vậy, git ls-files -o --exclude-standard).]

... cũng có thể dễ dàng viết kịch bản - ngay cả các bí danh cũng được thực hiện (được trình bày theo cú pháp zsh; điều chỉnh khi cần thiết) [tôi cũng rút ngắn tên tệp để tất cả khớp với màn hình mà không cuộn trong câu trả lời này; vui lòng thay thế một tên tệp thay thế mà bạn chọn]:

alias stashall='git ls-files -o > .gftu; git add `cat .gftu`; git stash'
alias unstashall='git stash pop; git rm --cached `cat .gftu`; rm .gftu'

Lưu ý rằng cái sau có thể tốt hơn như là một tập lệnh shell hoặc hàm, để cho phép các tham số được cung cấp cho git stash, trong trường hợp bạn không muốn popnhưng apply, và / hoặc muốn có thể chỉ định một ngăn cụ thể, thay vì chỉ lấy đầu một. Có lẽ điều này (thay vì bí danh thứ hai, ở trên) [khoảng trắng bị tước để phù hợp mà không cần cuộn; thêm lại để tăng mức độ dễ đọc]:

function unstashall(){git stash "${@:-pop}";git rm --cached `cat .gftu`;rm .gftu}

Lưu ý : Trong biểu mẫu này, bạn cần cung cấp một đối số hành động cũng như mã định danh nếu bạn sẽ cung cấp một mã định danh stash, ví dụ unstashall apply stash@{1}hoặcunstashall pop stash@{1}

Tất nhiên những gì bạn đặt vào .zshrchoặc tương đương để tồn tại lâu dài.

Hy vọng câu trả lời này hữu ích cho ai đó, kết hợp tất cả mọi thứ lại với nhau trong một câu trả lời.


1
git ls-files -o hiển thị nhiều tệp hơn những tệp tôi quan tâm. từ trạng thái git sau đây tôi thấy thêm - hoạt động tiêu chuẩn. git ls-files -o --exclude-standard. Tôi đồng ý rằng đây chỉ là "bao gồm" các tệp không bị theo dõi mà bạn thường không bỏ qua, tức là chỉ hiển thị các tệp chưa được đóng gói mà .gitignore của bạn sẽ không lọc ra
mancocapac 22/03/2017

20

Trên git phiên bản 2.8.1: hoạt động sau đây cho tôi.

Để lưu các tệp đã sửa đổi và không bị theo dõi trong stash mà không có tên

git stash save -u

Để lưu các tệp đã sửa đổi và không bị theo dõi trong stash với một tên

git stash save -u <name_of_stash>

Bạn có thể sử dụng pop hoặc áp dụng sau như sau.

git stash pop

git stash apply stash@{0}

Điều này đã không xóa các tệp không bị theo dõi khỏi máy tính của tôi, mặc dù chúng không còn được liệt kê là không bị theo dõi. git stash showđã không cho họ thấy. Khi tôi thử git stash apply, tôi gặp "lỗi: không thể khôi phục các tệp không bị theo dõi từ stash". Tuy nhiên, các tệp sau đó một lần nữa được liệt kê là không bị theo dõi, nhưng các thay đổi đối với các tệp được theo dõi không được khôi phục. Tôi nghĩ rằng các tệp đó có thể được khôi phục riêng lẻ bằng cách kiểm tra chúng ra khỏi ngăn chứa, nhưng giải pháp này không phải là điều tôi mong muốn.
hBrent

9

Tôi đã có thể stash chỉ các tập tin chưa được theo dõi bằng cách làm:

git stash save "tracked files I'm working on"
git stash save -u "untracked files I'm trying to stash"
git stash pop stash@{1}

Cái cuối cùng bật ra stash của các tệp được theo dõi, do đó chỉ để lại các tệp không bị bẻ khóa.


git stash save -ukhông chỉ lưu các untrackedtập tin, nó lưu cả trackeduntracked. Tôi nghĩ rằng tiết kiệm đầu tiên bạn đang làm là không cần thiết trong trường hợp này. Có một sơ đồ tốt trong atlassian.com/git/tutorials/saving-changes/
mài

2
Câu hỏi là làm thế nào để stash chỉ các tập tin không bị theo dõi. Nếu bạn bỏ qua stash đầu tiên, thì bạn sẽ bật cái gì? Ý tưởng là: 1) Stash được theo dõi. 2) Stash không bị theo dõi. 3) Pop theo dõi. Kết quả: Unracked vẫn bị cất giấu.
Oded

3

Nếu bạn muốn bỏ các tệp không bị theo dõi, nhưng giữ các tệp được lập chỉ mục (ví dụ như các tệp bạn sắp cam kết), chỉ cần thêm -ktùy chọn (giữ chỉ mục) vào tùy chọn-u

git stash -u -k


2

hãy giả sử tập tin mới và không bị theo dõi được gọi là: "view.json". nếu bạn muốn thay đổi chi nhánh bằng cách xóa trạng thái của ứng dụng, tôi thường gõ:

git add views.json

Sau đó:

git stash

Và nó sẽ được cất giấu. Sau đó tôi có thể thay đổi chi nhánh với

git checkout other-nice-branch

1

Có một số câu trả lời đúng ở đây, nhưng tôi muốn chỉ ra rằng đối với toàn bộ thư mục mới, 'git add path'sẽ KHÔNG hoạt động. Vì vậy, nếu bạn có một loạt các tệp mới trong đường dẫn không bị theo dõi và làm điều này:

git add untracked-path
git stash "temp stash"

cái này sẽ chứa thông báo sau:

Saved working directory and index state On master: temp stash
warning: unable to rmdir untracked-path: Directory not empty

và nếu con đường không bị theo dõicon đường duy nhất bạn đang sử dụng, thì stash "temp stash" sẽ là một ngăn trống. Cách chính xác là thêm toàn bộ đường dẫn, không chỉ tên thư mục (tức là kết thúc đường dẫn bằng dấu '/'):

git add untracked-path/
git stash "temp stash"

Ít nhất trên hệ thống của tôi giả định của bạn là sai. Nó hoạt động mà không có dấu gạch chéo! Thư mục trống được bỏ qua anyway. (macos git 2.6.2)
phobie

0

Tôi nghĩ rằng điều này có thể được giải quyết bằng cách nói với git rằng tập tin tồn tại, thay vì cam kết tất cả nội dung của nó vào khu vực tổ chức, và sau đó gọi git stash. Araqnid mô tả cách làm trước đây.

git add --intent-to-add path/to/untracked-file

hoặc là

git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 path/to/untracked-file

Tuy nhiên, cái sau không hoạt động:

$ git stash
b.rb: not added yet
fatal: git-write-tree: error building trees
Cannot save the current index state

1
Theo như tôi có thể nói, cái trước cũng không hoạt động. Xem câu trả lời của tôi cho một giải pháp cho vấn đề này.
lindes

0
git stash --include-untracked

yêu thích của tôi vì nó cũng lưu các tệp mà bạn đã thêm và chưa dàn dựng chúng.


0

Tôi đã gặp một vấn đề tương tự trong khi sử dụng Sourcetree với các tệp mới được tạo (chúng cũng sẽ không được bao gồm trong stash).

Khi tôi lần đầu tiên chọn 'giai đoạn tất cả' và sau đó bỏ các thành phần mới được thêm vào nơi được theo dõi và do đó được bao gồm trong ngăn.


Câu hỏi này đã 11 tuổi và đã có 14 câu trả lời. Bạn đã đọc chúng trước khi đăng?
Mickael B.

-7

Tôi đã từng suy ngẫm và mong muốn tính năng tương tự. Nhưng theo thời gian, tôi nhận thấy nó thực sự không cần thiết. Khi bạn bỏ rác, bạn có thể rời khỏi các tệp mới. Không có gì "xấu" có thể xảy ra với họ (khi bạn kiểm tra một cái gì đó khác, git sẽ báo lỗi và không ghi đè lên tệp không bị theo dõi hiện có)

Và vì thông thường khung thời gian giữa git stashgit stash popkhá nhỏ, bạn sẽ cần nhanh chóng cần lại tệp không bị theo dõi. Vì vậy, tôi sẽ nói rằng sự bất tiện của tệp hiển thị trong git statuskhi bạn đang làm việc với một thứ khác (giữa git stashgit stash pop) là nhỏ hơn sau đó là sự bất tiện do công việc gây ra và cần phải chú ý nếu không sẽ cố gắng thêm tệp không bị theo dõi vào stash của bạn.


15
Nó phụ thuộc vào dự án. Giả sử tệp không bị theo dõi là một thử nghiệm đơn vị (nửa viết) và khai thác thử nghiệm chạy tất cả các thử nghiệm đơn vị trong thư mục. V.v.
Steve Bennett

1
Một ví dụ khác là nếu bạn làm việc trên hai máy tính và bạn được phép di chuyển dữ liệu từ A sang B, nhưng không phải từ B sang A. Nếu bạn tạo một đoạn mã mới để giải quyết vấn đề xảy ra đầu tiên trên B nhưng đó là bạn muốn trên cả A và B, bạn muốn có thể lưu tệp trên B để khi bạn tạo lại tệp đó trên A và sau đó mang lại trong một gói, bạn có thể git diff phiên bản được lưu để xác minh rằng bạn đã không mắc lỗi
Gdalya

7
Chỉ vì một tệp không được theo dõi trong một nhánh, không có nghĩa là nó sẽ không xung đột với tệp được theo dõi ở nhánh khác.
JWG

3
ví dụ phản biện đơn giản: Tệp cấu hình trong thư mục .conf.d hoặc bất kỳ tệp nào khác chỉ bằng cách ở đó sửa đổi hành vi của phần mềm.
fotanus

Tất nhiên các chức năng là cần thiết. Đó là một ví dụ bổ sung, không thể chuyển từ chi nhánh này sang chi nhánh khác nếu bạn có các tệp không bị theo dõi cục bộ mà bạn muốn lưu trữ.
Dân chủ
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.