Cách thực hành tốt nhất để sao chép git sao chép vào một thư mục hiện có?


480

Tôi có một bản sao làm việc của dự án, không có bất kỳ dữ liệu meta kiểm soát nguồn nào. Bây giờ, tôi muốn thực hiện tương đương git-clone vào thư mục này và giữ các thay đổi cục bộ của tôi.

git-clone không cho phép tôi sao chép vào một thư mục hiện có. Thực hành tốt nhất ở đây là gì?


4
Thảo luận tốt hơn là ở đây .
cdunn2001

1
@MEM Tôi thích câu trả lời này hơn, nhưng hoạt động ... stackoverflow.com/a/5377989/11236
ripper234

2
@ ripper234 - Vâng. Tôi đã ở trong tình huống tương tự và tôi chỉ làm những bước đó, và không có vấn đề gì. Tất cả đều sạch đẹp. Tôi đoán đó là vấn đề ưu tiên, điểm mấu chốt là cả hai đều hoạt động, như bạn nêu. Chúc mừng.
MEM

1
Điều này thật điên rồ, không có cách nào để đạt được nó, rất hữu ích khi bạn muốn sao chép một projet vào một thư mục chia sẻ được gắn kết.
Thomas Decaux

Câu trả lời:


559

Điều này có thể được thực hiện bằng cách nhân bản vào một thư mục mới, sau đó di chuyển .gitthư mục vào thư mục hiện có của bạn.

Nếu thư mục hiện tại của bạn được đặt tên là "mã".

git clone https://myrepo.com/git.git temp
mv temp/.git code/.git
rm -rf temp

Điều này cũng có thể được thực hiện mà không cần thực hiện kiểm tra trong lệnh clone; thêm thông tin có thể được tìm thấy ở đây .


25
Lưu ý rằng đây chính xác là đề xuất từ ​​@ChrisJohnsen mà anh ấy để lại trong các bình luận. Tôi thấy nó hữu ích và muốn biến nó thành một câu trả lời thực sự. Chris, nếu bạn kết thúc một câu trả lời, tôi sẽ vui vẻ xóa câu trả lời này.
amellyas

2
Cảm ơn! Mặc dù điều này thiếu một bước như "kiểm tra git -." vì nó nghĩ rằng tất cả các tập tin bị xóa, phải không?
mrooney

2
Không, miễn là bạn sử dụng git clonelàm lệnh đầu tiên, không cần thêm lệnh kiểm tra. Thay vào đó, nếu bạn sử dụng một cái gì đó giống như git clone --no-checkouttrong bước đầu tiên, thì sau khi thư mục .git được di chuyển, sẽ cần phải sử dụng git reset HEADđể nói với git rằng các tệp chưa bị xóa.
amellyas

3
Tôi sẽ thêm bước này như bước thứ ba: mv temp / .gitignore code / .gitignore
Daniel Aranda

1
@KalpeshSoni, vâng git sẽ biết về các tệp đã sửa đổi và có thể thấy các thay đổi bằng cách sử dụng các lệnh git bình thường như git status.
amellyas

284

Đừng sao chép, tìm nạp thay thế. Trong repo:

git init
git remote add origin $url_of_clone_source
git fetch origin
git checkout -b master --track origin/master # origin/master is clone's default

Sau đó, bạn có thể đặt lại cây để nhận được cam kết bạn muốn:

git reset origin/master # or whatever commit you think is proper...

và bạn giống như bạn nhân bản.

Câu hỏi thú vị ở đây (và câu hỏi không có câu trả lời): Làm thế nào để tìm ra cam kết nào mà cây trần trụi của bạn dựa vào, từ đó đặt lại vị trí nào.


7
Tôi không phải là người hâm mộ điều này - mỗi thiết lập github "Mẹo: Trình trợ giúp thông tin chỉ hoạt động khi bạn sao chép URL kho lưu trữ HTTPS." Tôi đã sử dụng người trợ giúp thông tin và điều này đã gửi cho tôi một lỗ thỏ khá dài và không có kết quả.
Andrew

5
'git checkout --track origin / master' cũng hoạt động tốt thay vì 'git checkout -b master --track origin / master'. Việc thiết lập lại là không cần thiết.
felipecrp

1
Tôi đã nhận được lỗi "Lỗi Git: Các tệp cây làm việc không được theo dõi sau đây sẽ bị ghi đè bởi thanh toán", vì vậy tôi thêm lệnh này: git clean -d -fx ""
shakaran

1
chắc chắn không nên trong mọi tình huống, nhưng đây chính xác là những gì tôi cần.
Chaim Eliyah

1
@AndreasKrey Câu trả lời ban đầu của bạn (mà tôi đã đi vào lịch sử chỉnh sửa để xem) thực hiện chính xác những gì cần thiết cho câu hỏi (và tôi). Các barfs câu trả lời đã thay đổi khi thanh toán mà không sử dụng -f, loại bỏ các thay đổi cục bộ và chính xác là những gì tôi không muốn. Nếu tôi là bạn, tôi sẽ cân nhắc quay lại câu trả lời ban đầu của bạn.
Ajean

77

Tôi đã làm như sau, để kiểm tra nhánh chính trong một thư mục hiện có:

git init
git remote add origin [my-repo]
git fetch
git checkout origin/master -ft

2
Đây là một câu trả lời tuyệt vời và tránh bất kỳ sự tinh chỉnh hệ thống tập tin.
dùng151841

1
Đây phải là câu trả lời được chấp nhận vì nó không phải là một hack.
php_nub_qq

5
Trên thực tế, điều này thực hiện chính xác những gì OP (và tôi) không muốn, đó là ghi đè lên các thay đổi cục bộ.
Ajean

Upvote của tôi chỉ ra rằng điều này đã giúp tôi, không phải đó là câu trả lời tốt nhất cho câu hỏi của OP.
TecBrat

2
Ai đó có thể giải thích tại sao -tcờ được sử dụng ở đây?
jfowkes

38

Tôi muốn git cloneđến một thư mục mới và sao chép nội dung của thư mục hiện có vào bản sao mới.


4
nếu bạn làm điều đó, hãy đảm bảo bạn xem xét khác biệt trước khi thực hiện cẩn thận - đây là trường hợp cổ điển tuyệt đối khi bạn có thể vô tình hoàn nguyên các thay đổi được thực hiện trong repo nguồn kể từ khi bạn nhận được bản sao làm việc của mình - vì không có đủ thông tin trong bản sao làm việc để tìm ra những thay đổi bạn đã thực hiện so với những thay đổi trước khi bạn bắt đầu thực hiện thay đổi, để hợp nhất với những thay đổi khác được thực hiện trong repo. Tôi đã thấy điều này xảy ra hết lần này đến lần khác trong tình huống này, đến mức tôi "nản lòng" bản thân và những người mà tôi đã làm việc cùng nhau từ trước đến giờ.
Ben Clifford

72
git clone wherever tmp && git mv tmp/.git . && rm -rf tmpNói cách khác, di chuyển .gitthư mục ra khỏi một bản sao tạm thời có vẻ đơn giản hơn việc dọn sạch cây làm việc của bản sao và sao chép các tệp hiện có ở đó.
Chris Johnsen

1
@ChrisJohnsen: bạn nên đưa ra câu trả lời, đó chắc chắn là cách tốt nhất để làm điều đó imho
Stefano

2
@ChrisJohnsen git mv tmp/.git .trả lại fatal: cannot move directory over file, source=tmp/.git, destination=.gitcho tôi. Bất cứ ai cũng biết vấn đề là gì?
Dennis

6
@Dennis, Đó là một lỗi đánh máy: lệnh đó nên đơn giản mv, không git mv; mặc dù điều này không giải thích lý do tại sao bạn đã có một .gittập tin ở đó (có chứa gitdir: some/path/to/a/git-dir, một gitfile, nhưng nếu nó không có ở đó, thì bạn sẽ thấy fatal: Not a git repository (or any of the parent directories): .gitthay thế).
Chris Johnsen

34

Sử dụng một thư mục tạm thời là tốt, nhưng điều này sẽ hoạt động nếu bạn muốn tránh bước đó. Từ thư mục gốc của thư mục làm việc của bạn:

$ rm -fr .git
$ git init
$ git remote add origin your-git-url
$ git fetch
$ git reset --mixed origin/master

20
git reset --hard origin/mastersẽ loại bỏ bất kỳ tập tin cục bộ.
Mouad Debbar

1
để thêm vào những gì đã chỉ ra ở trên, sự khác biệt giữa hardmixedhỗn hợp sẽ giữ các thay đổi cục bộ (vì vậy nếu sau này bạn cố gắng kéo nó sẽ hiển thị cho bạn, ví dụ: Không thể kéo theo rebase: Bạn có các thay đổi không được thực hiện. Vui lòng cam kết hoặc bỏ qua chúng ) , trong khi khó sẽ loại bỏ những thay đổi cục bộ đó
aexl

Bạn viết sai chính tả từ xa.
Glenn Dayton

10
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed

7
Việc sử dụng git reset --hardsẽ giúp thay đổi tập tin cục bộ, đặc biệt KHÔNG phải những gì OP này yêu cầu. --mixednên được sử dụng thay thế.
Caleb

4

Để sao chép một git repo vào một thư mục hiện có trống, hãy làm như sau:

cd myfolder
git clone https://myrepo.com/git.git . 

Lưu ý .ở cuối git clonelệnh của bạn . Điều đó sẽ tải repo vào thư mục làm việc hiện tại.


4
fatal: destination path '.' already exists and is not an empty directory.
Roland Kofler

Thư mục phải trống.
okTalk

4
OP đang yêu cầu làm thế nào để sao chép vào một dự án hiện có, nói rằng git clone phàn nàn. Câu trả lời không hay.
mix3d

Điều này chỉ hoạt động khi bạn tạo thư mục mới, chạy các lệnh trên mà không sử dụng "git init"
Bilal Ahmed

3

Rất nhiều câu trả lời đã được thực hiện theo cách mà OP yêu cầu. Nhưng điều đáng chú ý là thực hiện theo cách ngược lại đơn giản hơn nhiều:

git clone repo-url tmp/
cp -R working/ tmp/

Bây giờ bạn có trạng thái mục tiêu mong muốn - bản sao mới + thay đổi cục bộ.


2

Có hai cách tiếp cận này. Nếu có thể tôi sẽ bắt đầu với một thư mục sạch cho thư mục git làm việc mới của bạn và sau đó sao chép phiên bản của bạn sau này. Cái này có thể trông giống như *:

mv $dir $dir.orig
git clone $url $dir
rsync -av --delete --exclude '.git' $dir.orig/ $dir/
rm -rf $dir.orig

Tại thời điểm này, bạn nên có một bản sao làm việc khá sạch sẽ với thư mục làm việc trước đó của bạn như thư mục làm việc hiện tại để mọi thay đổi bao gồm xóa tệp sẽ hiển thị trên radar nếu bạn chạy git status.

Mặt khác, nếu bạn thực sự phải làm theo cách khác, bạn có thể nhận được kết quả tương tự với một cái gì đó như thế này:

cd $dir
git clone --no-checkout $url tempdir
mv tempdir/.git .
rmdir tempdir
git reset --mixed HEAD

Dù bằng cách nào, điều đầu tiên tôi sẽ làm là chạy một cái gì đó như git stash lấy một bản sao của tất cả các thay đổi cục bộ của bạn sang một bên, sau đó bạn có thể áp dụng lại chúng và làm việc thông qua những gì bạn muốn cam kết.

* Cả hai ví dụ đều cho rằng bạn bắt đầu trên shell trong thư mục mẹ của dự án.


2

Đây là phương pháp tốt nhất trong tất cả các phương pháp tôi đã tìm thấy

Chỉ sao chép thư mục .git của kho lưu trữ (không bao gồm các tệp khi chúng đã có existing-dir) vào một thư mục tạm thời trống

  1. git clone --no-checkout repo-path-to-clone existing-dir/existing-dir.tmp // có thể muốn --no-hardlinks để nhân bản repo cục bộ

Di chuyển thư mục .git vào thư mục chứa các tệp. Điều này làm cho existing-dirmột repo git.

  1. mv existing-dir/existing-dir.tmp/.git existing-dir/

Xóa thư mục tạm thời

  1. rmdir existing-dir/existing-dir.tmp

  2. cd existing-dir

Git nghĩ rằng tất cả các tệp đã bị xóa, điều này hoàn nguyên trạng thái của repo thành CHÍNH.

CẢNH BÁO: mọi thay đổi cục bộ đối với các tệp sẽ bị mất.

  1. git reset --mixed HEAD

1
Thiết lập lại cứng dường như không mong muốn trong 99% trường hợp bạn cần thực hiện việc này.
Stefan Fabian

0

Nếu bạn đang sử dụng ít nhất git 1.7.7 (mà dạy clonecác --configtùy chọn), để biến thư mục hiện hành thành một bản sao làm việc:

git clone example.com/my.git ./.git --mirror --config core.bare=false

Điều này hoạt động bởi:

  • Nhân bản kho lưu trữ vào một .gitthư mục mới
  • --mirrorlàm cho bản sao mới vào một thư mục siêu dữ liệu hoàn toàn .gitcần thiết
  • --config core.bare=falseđối phó với ẩn bare=truecủa --mirrortùy chọn, do đó cho phép kho lưu trữ có một thư mục làm việc liên quan và hoạt động như một bản sao bình thường

Điều này rõ ràng sẽ không hoạt động nếu một .gitthư mục siêu dữ liệu đã tồn tại trong thư mục bạn muốn biến thành một bản sao làm việc.


1
Lưu ý rằng kỹ thuật này sẽ dẫn đến [core]phần cấu hình cục bộ bao gồm cả bare = true bare = false . Vấn đề hơn là nó sẽ có các giá trị sai cho originđiều khiển từ xa, với [remote "origin"]phần bao gồm mirror = truevà một thông số tìm nạp sẽ không hoạt động đúng với một bản sao làm việc. Sau khi khắc phục các sự cố này, nhân bản bình thường và di chuyển bản sao làm việc mới .gitsẽ hiệu quả hơn.
Araxia

0

Thông thường tôi sẽ sao chép kho lưu trữ ban đầu trước, sau đó di chuyển mọi thứ trong thư mục hiện có sang kho lưu trữ ban đầu. Nó hoạt động mọi lúc.

Ưu điểm của phương pháp này là bạn sẽ không thiếu bất cứ thứ gì của kho lưu trữ ban đầu bao gồm README hoặc .gitignore.

Bạn cũng có thể sử dụng lệnh dưới đây để hoàn thành các bước:

$ git clone https://github.com/your_repo.git && mv existing_folder/* your_repo

0

Bạn có thể làm điều đó bằng cách gõ đệ quy các dòng lệnh sau:

mkdir temp_dir   //  Create new temporary dicetory named temp_dir
git clone https://www...........git temp_dir // Clone your git repo inside it
mv temp_dir/* existing_dir // Move the recently cloned repo content from the temp_dir to your existing_dir
rm -rf temp_dir // Remove the created temporary directory

0

Chỉ cần sử dụng. ở cuối git clonelệnh (nằm trong thư mục đó), như thế này:

cd your_dir_to_clone_in/
git clone git@github.com/somerepo/ .
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.