Làm thế nào để giai đoạn chỉ là một phần của một tập tin mới với git?


221

Tôi yêu git add - tương tác . Bây giờ nó là một phần của quy trình làm việc hàng ngày của tôi.

Vấn đề có vẻ như nó không hoạt động với các tập tin không được theo dõi. Những gì tôi muốn làm là theo dõi một tệp mới, nhưng chỉ thêm một phần của nó, tức là một số phần của tệp mới này chưa sẵn sàng để được dàn dựng.

Ví dụ, với git add -i, tôi có thể chọn tùy chọn vá và thậm chí chỉnh sửa từng khối riêng lẻ để giai đoạn các phần của mã mới, không để lại các bình luận mã gỡ lỗi. Tôi thích làm việc theo cách này bởi vì nó rõ ràng những nơi nào của bản vá lớn mà tôi hiện đang làm việc vẫn cần làm việc.

Thật không may, tôi dường như không thể làm điều tương tự với một tập tin không bị theo dõi. Hoặc tôi giai đoạn toàn bộ tập tin, hoặc không có gì. Cách giải quyết mà tôi đang sử dụng là dàn dựng hoặc thậm chí cam kết một tệp mới khi nó trống, và sau đó dàn dựng các thay đổi riêng lẻ theo cách thông thường. Nhưng giải pháp này cảm thấy giống như một bản hack bẩn và khi tôi quên, hoặc thay đổi suy nghĩ của mình, nó sẽ tạo ra nhiều rắc rối hơn mức cần thiết.

Vì vậy, câu hỏi là: Làm thế nào để giai đoạn chỉ một phần của một tệp mới, để tệp mới này được theo dõi nhưng để lại toàn bộ hoặc một phần nội dung của nó không được đặt ra?

Câu trả lời:


415

Whoa, tất cả điều đó update-indexhash-objectkinh doanh dường như quá phức tạp. Làm thế nào về điều này thay thế:

git add -N new_file
git add -i

Từ git help add:

-N, --intent-to-add
    Record only the fact that the path will be added later.  An entry
    for the path is placed in the index with no content.  This is useful
    for, among other things, showing the unstaged content of such files
    with git diff and committing them with git commit -a.

9
++ 1! đáo hạn tín dụng. Tôi tin tưởng một chút quá nhiều đến bây giờ tôi biết những trang này ....</shame>
sehe

1
Cũng được tìm thấy. Tôi nên cuộn trang người đàn ông thêm một chút. Có lẽ tôi nên trả lại huy hiệu Git Pro.
dave1010

3
Tự hỏi tại sao git-gui không sử dụng nội bộ này để có thể tạo các dòng từ một tệp mới.
Deiwin

6
-NKhám phá tuyệt vời , cảm ơn! Mặc dù tôi muốn kết hợp nó với -ptrong trường hợp đó. gid add -N the_file& git add -p. Một người nên thêm nó -Ncũng hoạt động với-A
Cyril CHAPON

@Deiwin - bạn có thể thêm [guitool] vào .gitconfig để thực hiện "git add -N $ FILENAME": [guitool "Thêm với ý định"] cmd = "git add -N $ FILENAME"
Steve Folly

7

Cách dễ nhất để làm điều này (và dàn dựng tương tác imho nói chung) là git gui. Nó đi kèm với git và sẽ hoạt động trên hầu hết các nền tảng được hỗ trợ bởi git.

Đơn giản chỉ cần chạy git guivà một gui sẽ mở cho phép dàn dựng và không dàn dựng và thậm chí các dòng duy nhất của các tệp được theo dõi và không bị theo dõi.

Ảnh chụp màn hình Git Gui


Đây là một câu trả lời sáng tạo và đôi khi nó rất, rất hữu ích.
Pablo Olmos de Aguilera C.

3
Chỉ cần một lưu ý rằng không phải tất cả các phân phối git bao gồm git gui. Ví dụ, trong Debian, nó nằm trong một gói riêng gọi là 'git-gui'.
cristoper

Đã tìm kiếm (không đủ khó) cho tính năng này trong nhiều năm, đây là một thay đổi cuộc sống
austinmarton

2
Đối với tôi, việc dàn dựng các dòng duy nhất của các tệp git guichưa được theo dõi chưa bao giờ hoạt động. Trong thực tế, nó vô hiệu hóa các tùy chọn menu .
Deiwin

2
@Deiwin Tôi thực sự đã bỏ lỡ điều này trong câu hỏi - ảnh chụp màn hình của tôi cho thấy một tập tin đã được theo dõi. Nếu bạn muốn sử dụng git guicho một tệp mới, git add -N new_filetrước tiên bạn phải chạy - xem câu trả lời của Richard Hansen.
Chronial

6
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
git add --interactive newfile

Bản demo đơn giản:

mkdir /tmp/demo
cd /tmp/demo
git init .

echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • Gợi ý Nếu bạn chắc chắn blob 'trống' đã tồn tại trong cơ sở dữ liệu đối tượng git của mình, bạn có thể mã hóa băm e69de29bb2d1d6434b8b29ae775ad8c2e48c5391thay thế. Tôi không khuyên bạn nên làm điều đó_
  • Gợi ý Nếu bạn đang dùng Windows, có lẽ bạn chỉ có thể sử dụng NUL:thay vì /dev/null. Nếu không, sử dụng một cái gì đó nhưecho -n '' | git hash-object --stdin -w

Bây giờ chỉ mục sẽ chứa newfiledưới dạng blob trống và blob trống đã được nhập vào cơ sở dữ liệu đối tượng nếu nó chưa tồn tại:

$ find .git/objects/ -type f 
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   newfile
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   newfile
#

$ git diff
diff --git a/newfile b/newfile
index e69de29..ce01362 100644
--- a/newfile
+++ b/newfile
@@ -0,0 +1 @@
+hello

Điều này nên chính xác những gì bạn muốn. Tôi cũng có thể giới thiệu plugin vim fugitive để quản lý chỉ mục rất thông minh (xem phần bổ sung git tốt hơn -p? )


1
Điều này dường như làm việc tốt. Tôi đã đặt bí danh cho "tập tin sân khấu trống" vì nó hơi phức tạp để nhớ.
dave1010

@ dave1010: Rất vui vì điều đó đã giúp! Vâng, tôi đã nghĩ về việc thêm một bí danh, nhưng tôi không biết bạn sẽ xử lý như thế nào, ví dụ như các ký tự đại diện hoặc nhiều đối số tên tệp nói chung. Vì vậy, tôi đã chọn không tham gia
sehe

2

Chỉnh sửa: điều này dường như không hoạt động bây giờ. Tôi chắc chắn đó là trước đây (trên git 1.7.1). Trong trường hợp nó không hoạt động, tôi đề nghị dàn dựng /dev/nullnhư sehe gợi ý ở trên:

git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile

Nếu bạn đang ở trên Windows (không có /dev/null) thì bạn có thể thay thế nó bằng đường dẫn đến một tệp trống.

Câu trả lời gốc

Bạn muốn

git add -p # (or --patch)

Điều này thêm các tập tin chưa được theo dõi cho tôi. Từ trang người đàn ông:

Tương tác chọn các miếng vá giữa chỉ mục và cây công việc và thêm chúng vào chỉ mục. Điều này cung cấp cho người dùng cơ hội để xem xét sự khác biệt trước khi thêm nội dung được sửa đổi vào chỉ mục.

Điều này thực sự chạy add --interactive, nhưng bỏ qua menu lệnh ban đầu và trực tiếp nhảy đến tiểu ban bản vá. Xem chế độ tương tác trực tuyến để xem chi tiết.


2
Tuy nhiên, thật thú vị, nó không hoạt động với tôi (git 1.7.4); git add -p newfilehoàn toàn không hoạt động (hiệu ứng nu) và git add --interactive'[a] dd không bị theo dõi' có tác dụng git add newfile; Chỉnh sửa cũng được kiểm tra với git 1.7.5.3; không có xúc xắc
sehe

Gợi ý tốt cho Windows, thêm gợi ý cho câu trả lời của tôi. Thx
sehe

-3

Chỉ để ghi lại khả năng khác: tôi sử dụng

git add -N file
git add -p file

Và sau đó bạn có thể giai đoạn hunk, hoặc chỉnh sửa chúng tại chỗ.


1
Câu trả lời này nói giống như câu trả lời được chấp nhận, bắt đầu từ năm 2011. Downvote.
Stanislav Pankevich

Câu trả lời được chấp nhận kết hợp add -Nvới add -i. Tôi chỉ nói thêm rằng add -pthay vì add -ilàm việc, quá.
Pedro Adame Vergara
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.