lệnh git để di chuyển một thư mục bên trong một thư mục khác


193

Tôi đã tạo một thư mục commonvới một loạt các tệp và thư mục nguồn.

Bây giờ tôi muốn chuyển commonthư mục vào includethư mục để nó trông giống nhưinclude/common

Tôi đã thử những điều này:

  1. git add include

  2. git mv common/ include/

    nhưng nó không thành công với lỗi này

    gây tử vong: nguồn xấu, nguồn = myrepo / chung, đích = myrepo / bao gồm

  3. Tôi đã thử git mv common/ include/commonnhưng tôi gặp lỗi tương tự

Bất kỳ ý tưởng làm thế nào để đạt được điều này?

Câu trả lời:


177

Một trong những điều thú vị nhất về git là bạn không cần phải theo dõi rõ ràng việc đổi tên tập tin. Git sẽ tìm ra nó bằng cách so sánh nội dung của các tập tin.

Vì vậy, trong trường hợp của bạn, đừng làm việc quá sức:

$ mkdir include
$ mv common include
$ git rm -r common
$ git add include/common

Chạy git statussẽ cho bạn thấy một cái gì đó như thế này:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    common/file.txt -> include/common/file.txt
#

43
Điều này không phù hợp với tôi (sử dụng Windows 7, 1.7.6.msysgit.0). Git nghĩ rằng các tệp cũ đã bị xóa và các tệp mới đã được thêm vào.
Bart

Hmm, có lẽ git sử dụng một số tiện ích bên ngoài để xác định độ giống nhau của tệp mà taht không hoạt động trên Windows? Đây là một phần cốt lõi của việc thực hiện git.
Andres Jaan Tack

13
@OliverF. Sửa chữa: git mvlà tương đương.
Andres Jaan Tack

25
"Một trong những điều thú vị nhất về git" - một trong những nhược điểm của tính năng hay này là nó bắt đầu thất bại khi bạn cũng sửa đổi tệp đã được đổi tên ở một mức độ đáng kể, khiến nó thấy xóa và thêm một tệp mới , thật lòng mà nói, thay vào đó tôi muốn đổi tên hỗ trợ rõ ràng hơn.
Erik Kaplun

2
Nếu git chuyển đổi kết thúc dòng, điều này dẫn đến sự cố được mô tả bởi @Bart. Để làm việc này, bạn phải làm như sau: git config --global core.autocrlf false
Mariano Dupont

162
 git mv common include

nên làm việc.

Từ git mvtrang người đàn ông :

git mv [-f] [-n] [-k] <source> ... <destination directory>

Ở dạng thứ hai, đối số cuối cùng phải là một thư mục hiện có; các nguồn đã cho sẽ được chuyển vào thư mục này .
Chỉ số được cập nhật sau khi hoàn thành thành công, nhưng thay đổi vẫn phải được cam kết.

Không " git add" nên được thực hiện trước khi di chuyển.


Lưu ý: " git mv A B/", khi Bkhông tồn tại dưới dạng thư mục, sẽ báo lỗi, nhưng không được.

Xem cam kết c57f628 của Matthieu Moy ( moy) cho Git 1.9 / 2.0 (Q1 2014):

Git được sử dụng để cắt dấu gạch chéo và tạo lệnh tương đương với ' git mv file no-such-dir', tạo ra tệp no-such-dir(trong khi dấu gạch chéo rõ ràng tuyên bố rằng nó chỉ có thể là một thư mục).

Bản vá này bỏ qua dấu gạch chéo cho đường dẫn đích.
Đường dẫn với dấu gạch chéo của nó được chuyển sang đổi tên (2), lỗi này với thông báo thích hợp:

$ git mv file no-such-dir/
fatal: renaming 'file' failed: Not a directory

2
Hoạt động hoàn hảo - và sử dụng có git mvvẻ như là một cách tiếp cận tốt hơn nhiều!
Tomas Petricek 17/03/2015

23

Chỉ huy:

$ git mv oldFolderName newFolderName

Nó thường hoạt động tốt.

Lỗi "nguồn xấu ..." thường chỉ ra rằng sau lần xác nhận cuối cùng, có một số đổi tên trong thư mục nguồn và do đó git mvkhông thể tìm thấy tệp dự kiến.

Giải pháp rất đơn giản - chỉ cần cam kết trước khi áp dụng git mv.


15

Đảm bảo bạn đã thêm tất cả các thay đổi của mình vào khu vực tổ chức trước khi chạy

git mv oldFolderName newFoldername

git không thành công

fatal: bad source, source=oldFolderName/somepath/somefile.foo, destination=newFolderName/somepath/somefile.foo

nếu có bất kỳ tập tin nào, vì vậy tôi chỉ cần tìm ra.


"nếu có bất kỳ tập tin chưa được xử lý, vì vậy tôi chỉ cần tìm ra." - cảm ơn!
mã hóa

3

Một cách khác để di chuyển tất cả các tệp trong một thư mục sang thư mục con (giữ lịch sử git):

$ for file in $(ls | grep -v 'subDir'); do git mv $file subDir; done;


3

Tôi gặp vấn đề tương tự với việc git mvtôi muốn chuyển nội dung của một thư mục vào thư mục hiện có và kết thúc với tập lệnh "đơn giản" này:

pushd common; for f in $(git ls-files); do newdir="../include/$(dirname $f)"; mkdir -p $newdir; git mv $f $newdir/$(basename "$f"); done; popd

Giải trình

  • git ls-files: Tìm tất cả các tệp (trong commonthư mục) được kiểm tra vào git
  • newdir="../include/$(dirname $f)"; mkdir -p $newdir;: Tạo một thư mục mới bên trong includethư mục, có cùng cấu trúc thư mục nhưcommon
  • git mv $f $newdir/$(basename "$f"): Di chuyển tệp vào thư mục vừa tạo

Lý do để làm điều này là vì git dường như có vấn đề khi di chuyển tệp vào các thư mục hiện có và nó cũng sẽ thất bại nếu bạn cố di chuyển tệp vào thư mục không tồn tại (do đó mkdir -p).

Điều thú vị về phương pháp này là nó chỉ chạm vào các tệp đã được kiểm tra để git. Bằng cách đơn giản là sử dụng git mvđể di chuyển toàn bộ thư mục và thư mục chứa các thay đổi chưa được xử lý, git sẽ không biết phải làm gì.

Sau khi di chuyển các tệp bạn có thể muốn dọn sạch kho lưu trữ để loại bỏ mọi thay đổi chưa được xử lý còn lại - chỉ cần nhớ chạy khô trước!

git clean -fd -n

2

Tôi xin lỗi tôi không có đủ danh tiếng để bình luận "câu trả lời" của "Andres Jaan Tack".

Tôi nghĩ tin nhắn của tôi sẽ bị xóa ((Nhưng tôi chỉ muốn cảnh báo "lurscher" và những người khác cũng có lỗi tương tự: hãy cẩn thận làm

$ mkdir include
$ mv common include
$ git rm -r common
$ git add include/common

Nó có thể khiến bạn sẽ không thấy lịch sử git của dự án của bạn trong thư mục mới.

tôi đã thử

$ git mv oldFolderName newFolderName

fatal: bad source, source=oldFolderName/somepath/__init__.py, dest
ination=ESWProj_Base/ESWProj_DebugControlsMenu/somepath/__init__.py

tôi đã làm

git rm -r oldFolderName

git add newFolderName

và tôi không thấy lịch sử git cũ trong dự án của tôi. Ít nhất dự án của tôi không bị mất. Bây giờ tôi có dự án của mình trong newFolderName, nhưng không có lịch sử (

Chỉ muốn cảnh báo, hãy cẩn thận khi sử dụng lời khuyên của "Andres Jaan Tack", nếu bạn không muốn mất đi sở thích của mình.


Hãy chắc chắn rằng tất cả các thay đổi của bạn đã được thêm vào. Git không nói "nguồn xấu" nếu có những thay đổi không được kiểm soát, vì vậy tôi mới phát hiện ra.
Kevin Pluck

0

Tôi gặp vấn đề tương tự, nhưng trong thư mục mà tôi muốn di chuyển tôi có các tệp mà tôi không theo dõi.

giả sử tôi có tập tin

a/file1
a/untracked1
b/file2
b/untracked2

Và tôi muốn chỉ chuyển các tệp được theo dõi sang thư mục con subdir, vì vậy mục tiêu là:

subdir/a/file1
subdir/a/untracked1
subdir/b/file2
subdir/b/untracked2

những gì tôi đã làm là:

  • Tôi đã tạo thư mục mới và di chuyển tất cả các tệp mà tôi quan tâm để di chuyển: mkdir tmpdir && mv a b tmpdir
  • kiểm tra các tập tin cũ git checkout a b
  • đã tạo thư mục mới và di chuyển các thư mục sạch (không có tệp không bị theo dõi) sang thư mục con mới: mkdir subdir && mv a b subdir
  • đã thêm tất cả các tệp từ thư mục con (vì vậy Git chỉ có thể thêm các tệp được theo dõi trước đó - đó là một số thủ thuậtgit add --update thay đổi thư mục ): (thông thường, điều này sẽ thêm các tệp thậm chí không bị theo dõi - điều này sẽ yêu cầu tạo tệp)git add subdir.gitignore
  • git status hiện chỉ hiển thị các tập tin di chuyển
  • chuyển phần còn lại của tệp từ tmpdir sang thư mục con: mv tmpdir/* subdir
  • git statuscó vẻ như chúng tôi đã thi hành git mv:)

-1

Tôi đã giải quyết điều này trên windows bằng cách làm điều này:

  • Bảng điều khiển vỏ mở
  • chạy dir
  • Nhấp chuột và kéo qua cột tên tệp / thư mục, sau đó sao chép
  • Dán vào notepad ++
  • chạy thay thế bằng regex: thay thế (.*)bằnggit mv ".\\\1" ".\\<New_Folder_Here>\"
  • sao chép tất cả văn bản từ notepad ++ vào powershell
  • Nhấn Enter
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.