2011-12-13 23 views
27
git mv file1 file2 

git status 
# On branch master 
# Changes to be committed: 
# (use "git reset HEAD <file>..." to unstage) 
# 
# renamed: file1 -> file2 

git stash 
git stash pop 

# On branch master 
# Changes to be committed: 
# (use "git reset HEAD <file>..." to unstage) 
# 
# new file: file2 
# 
# Changes not staged for commit: 
# (use "git add/rm <file>..." to update what will be committed) 
# (use "git checkout -- <file>..." to discard changes in working directory) 
# 
# deleted: file1 

Như bạn có thể thấy, git mất mối quan hệ được đổi tên sau dấu gạch chéo/bật. Có cách nào để lấy lại mối quan hệ này, hoặc có stash biết rằng các tập tin đã được di chuyển? Tôi thường stash để xem trạng thái hệ thống của tôi là như thế nào trước khi thay đổi, nhưng có nó mất mối quan hệ đổi tên là một vấn đề đối với tôi. Tôi không biết làm thế nào để sửa chữa nó khác hơn là xóa các tập tin mới, làm một git mv một lần nữa, và thay thế các nội dung của tập tin mới.stit và pop cho thấy tập tin không còn được đánh dấu là di chuyển?

+1

Lưu ý: wo đó uld là thú vị để thử lại với Git 2.12 (Q1 2017). Xem http: // stackoverflow.com/a/41307892/6309 – VonC

Trả lời

26

Nếu bạn chưa popped stash của bạn, làm:

git stash pop --index 

này một cách chính xác giữ gìn di chuyển (nhưng không cam kết) mối quan hệ tập tin trong một stash. Theo số git help stash:

Nếu tùy chọn --index được sử dụng, sau đó cố gắng khôi phục không chỉ những thay đổi của cây làm việc, mà còn thay đổi chỉ mục của chỉ mục. Tuy nhiên, điều này có thể thất bại, khi bạn có xung đột (được lưu trữ trong chỉ mục, do đó bạn không còn có thể áp dụng các thay đổi như ban đầu).

Nếu bạn đã popped stash của bạn và muốn tái tạo mối quan hệ di chuyển, làm:

git rm --cached file1 

này loại bỏ các "cũ" tập tin bất động từ chỉ số:

Sử dụng tùy chọn này để hủy ghép đoạn và chỉ xóa đường dẫn khỏi chỉ mục

+2

Tôi không biết liệu đây có phải là câu trả lời hay hơn so với "jit" của "Jefromi" –

+2

'git stash pop - index' là tốt hơn nếu bạn nhớ làm điều đó lần đầu tiên. Nhưng nếu trước đây bạn đã quên bật chỉ mục, 'git rm --cached file1' sẽ đưa bạn trở lại vị trí file2 được đổi tên bất kể. –

+0

Đó là một chút bất an. Tại sao git luôn luôn có những foibles nhỏ mà dường như ở đó chỉ để bắt bạn !? – Steve

18

Câu trả lời ngắn: git rm --cached file1

Tất cả git mv thực sự là đổi tên tập tin (trên hệ thống tập tin) và sau đó thêm một xóa tập tin và tạo cho các chỉ số (dàn khu vực). Nó không được đánh dấu đặc biệt. Máy móc khác sau đó nhận ra rằng đó là một sự đổi tên, bằng cách thấy rằng nội dung được gọi là file1 trước đây được gọi là file2.

Vì các lệnh git stash sửa đổi chỉ mục, chúng có thể làm xáo trộn mọi thứ. Lưu ý rằng bây giờ bạn đã tạo giai đoạn, nhưng không phải việc xóa! (Thông thường git-stash để lại mọi thứ chưa từng có sau một pop, nhưng trong trường hợp này tôi nghĩ rằng nó không có nhiều lựa chọn nhưng để đặt tập tin mới trong chỉ mục, để tránh bạn không biết nên giữ cái nào. bao giờ xảy ra với git stash pop --index, nhưng điều đó sẽ loại bỏ nếu các thay đổi được lưu trữ không thể được áp dụng một cách rõ ràng, vì vậy nó không được mặc định.) git status không thể hiển thị nó như một tên được nữa, bởi vì việc đổi tên có hiệu quả phân chia giữa chỉ mục và công việc cây và cả hai phần đều không thể xác nhận hoàn toàn.

Chỉ cần chạy git rm --cached file1 để xóa giai đoạn (ví dụ: xóa tệp1 khỏi chỉ mục) và nó sẽ hiển thị lại dưới dạng đổi tên. Bạn cũng có thể chạy git add -u để tự động thêm thay đổi, miễn là bạn không có thay đổi nào khác mà bạn không muốn chuyển sang giai đoạn. Lưu ý rằng điều này có nghĩa là trong thực tế bạn không cần phải lo lắng: khi bạn chuẩn bị mọi thứ chuẩn bị để cam kết (ví dụ: git add -u), "vấn đề" sẽ tự lo liệu.

Các vấn đề liên quan