2016-02-25 20 views
7

Tôi biết có rất nhiều câu hỏi hiện có trông giống nhau, vì vậy hãy để tôi tóm tắt chúng trước khi hỏi tôi.git, cách chắc chắn để di chuyển/đổi tên tệp trong khi vẫn giữ lịch sử

Câu trả lời cho câu hỏi đầu tiên, tôi không đồng ý, bởi vì tôi đã làm điều đó trước đây. Câu trả lời cho câu hỏi thứ hai là lý do tại sao tôi hỏi câu hỏi này. I.e.,

Tôi thấy mình đang làm git mv mọi lúc, nhưng đôi khi nó được coi là di chuyển/đổi tên và đôi khi nó được coi là xóa + bổ sung. Vì vậy, tôi muốn biết làm thế nào tôi có thể làm cho nó luôn luôn là một di chuyển/đổi tên?

Lấy this one làm ví dụ, ở dưới cùng, chúng ta có thể thấy một số trường hợp di chuyển/đổi tên, như easygenapi/tf-varcaser.go → tf-varcaser.go. Lưu ý rằng các di chuyển đó là trên/giữa các thư mục! I.e, I đã làm!

Nhưng có nhiều trường hợp khác git mv được coi là xóa + bổ sung, hiển thị trong cùng nhật ký thay đổi giống nhau. Một lần nữa, tôi đang làm git mv tất cả các lần. Tại sao git hoạt động khác?

Có cách nào chắc chắn cháy cách di chuyển/đổi tên tệp git trong khi vẫn giữ lịch sử?

Trả lời

9

tl; dr; không

Phiên bản dài hơn: Theo kinh nghiệm của tôi, git rất giỏi trong việc phát hiện di chuyển/đổi tên miễn là tệp chưa được sửa đổi. Git sử dụng heuristics để cố gắng và xác định vị trí di chuyển. Nó có thể bị lừa bởi có một số tệp quá giống nhau hoặc nếu tệp đã bị sửa đổi trong khi di chuyển, khiến nó quá khác so với tệp gốc của nó.

Cách tốt nhất tôi đã tìm thấy để thực hiện việc này là thực hiện các cam kết nhiều giai đoạn, tách tất cả các bước chuyển của bạn thành một cam kết, tiếp theo là các thay đổi trong một lần commit khác. Ví dụ:

git mv foo.txt bar.txt 
git commit 

... modify bar.txt ... 

git add bar.txt 
git commit 

Nó sẽ không đảm bảo di chuyển của bạn được phát hiện chính xác, vì nó vẫn có thể bị lẫn lộn khi có nhiều ứng cử viên. Tuy nhiên nó đã làm việc rất tốt cho tôi và nắm bắt phần lớn các trường hợp.

+0

Cảm ơn. Hữu ích hơn nhiều so với câu trả lời khác, * "Git không theo dõi các đổi tên. Thời gian." *, Có năm phiếu bầu trong khi điều này không có gì. ĐƯỢC. Tôi chắc chắn sẽ chơi * lừa nhiều giai đoạn * từ bây giờ và xem. – xpt

+0

Để công bằng, câu trả lời khác là nhiều thông tin hơn :) Tôi upvoted nó bản thân mình. Tôi đã thêm câu trả lời này bởi vì tôi cảm thấy nó quá trừu tượng và không trực tiếp trả lời câu hỏi của bạn. –

+0

Tôi vừa thử điều này, và mặc dù git hiển thị thay đổi là đổi tên trong khi cam kết, tôi vẫn * mất tất cả lịch sử thay đổi của mình cho tệp! – AnotherHowie

12

Git không theo dõi đổi tên. Giai đoạn. Nó cũng không theo dõi thêm. Hoặc xóa. Hoặc khác biệt. Hoặc các bản vá lỗi. Hoặc di chuyển. Hoặc bất kỳ sự thay đổi nào, thực sự.

Git dựa trên ảnh chụp nhanh. Mọi cam kết đều ghi lại ảnh chụp nhanh của toàn bộ dự án. Đó là nó. Làm thế nào ảnh chụp đó đã đến, Git không biết và cũng không quan tâm.

Sự khác biệt, bản vá, thêm, xóa, di chuyển, đổi tên, vv được hiển thị bằng các công cụ trực quan khác nhau, suy ra chúng sau khi sử dụng phương pháp chẩn đoán (đó là một cách khác để nói "đoán"). Đôi khi, họ có thể đoán chính xác những gì bạn đã làm, và đôi khi họ không. Mặc dù vậy, nó không quan trọng bởi vì nó chỉ là hình dung, nó không phải là một phần của lịch sử theo bất kỳ cách nào, hình dạng hay hình thức nào.

Hầu hết các công cụ đều sử dụng một số chỉ số tương tự và suy ra rằng việc đổi tên xảy ra nếu hai tệp có độ tương tự lớn hơn một số ngưỡng. Trong một số công cụ, ngưỡng này có thể định cấu hình được. Trong một số công cụ, ngay cả thuật toán cũng có thể cấu hình được. (Một ví dụ liên quan một chút: git diff cho phép bạn lựa chọn giữa các thuật toán khác nhau để suy luận về sự khác biệt trong tập tin.)

Kể từ Git không ghi lại những thay đổi, nó có thể để thêm những thay đổi mới trong các phiên bản sau này của các công cụ trực quan mà có thể phỏng đoán những thay đổi đó từ các cam kết cũ hơn đã được ghi lại trước khi các công cụ mới hiểu được các loại thay đổi mới thậm chí được viết. Hãy tưởng tượng, ví dụ, một công cụ mà hiểu cú pháp và ngữ nghĩa của ngôn ngữ lập trình bạn đang sử dụng. Nó có thể hình dung một cam kết nhất định không phải là một bó toàn bộ các tập tin có một vài dòng thay đổi, nhưng như là một thay đổi duy nhất mà đổi tên một chương trình con và cập nhật mỗi callite (tức làĐổi tên phương pháp đổi tên).

Đổi tên thực sự là một ví dụ điển hình về điều này. Ví dụ: chẩn đoán phát hiện đổi tên và số liệu tương tự được sử dụng bởi git log --follow được cải thiện nhiều lần. IIRC, lúc đầu, đổi tên không suy luận chút nào, khả năng đó được thêm vào sau. Điều này sẽ không thể thực hiện được nếu Git ghi lại thay đổi thay vì ảnh chụp nhanh.

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