Làm một xuất git gv khác (giống như xuất sv xuất sv)?


2356

Tôi đã tự hỏi liệu có một giải pháp "xuất git" tốt để tạo một bản sao của cây mà không có .gitthư mục kho lưu trữ. Có ít nhất ba phương pháp tôi biết:

  1. git clonetiếp theo là loại bỏ .gitthư mục kho lưu trữ.
  2. git checkout-index ám chỉ chức năng này nhưng bắt đầu bằng "Chỉ cần đọc cây mong muốn vào chỉ mục ..." mà tôi không hoàn toàn chắc chắn cách thực hiện.
  3. git-exportlà một kịch bản của bên thứ ba về cơ bản thực hiện một git clonevị trí tạm thời theo sau là rsync --exclude='.git'đích đến cuối cùng.

Không có giải pháp nào trong số này thực sự đánh tôi là thỏa đáng. Cái gần nhất svn exportcó thể là tùy chọn 1, vì cả hai đều yêu cầu thư mục đích trống trước. Nhưng tùy chọn 2 có vẻ tốt hơn nữa, giả sử tôi có thể hiểu được ý nghĩa của việc đọc một cây vào chỉ mục.


1
@rnrTom: Xem câu trả lời của Somov. (không có gì "nén" trong kho lưu trữ tar).
etarion

23
@mrTom git archive --format zip --output "output.zip" master -0sẽ cung cấp cho bạn một kho lưu trữ không nén (-0 là cờ cho không nén). git-scm.com/docs/git-archive .

7
Tôi đồng tình với @mrTom và tôi không nghĩ liệu kho lưu trữ bị nén hay không nén là vấn đề chính. Với SVN, tôi có thể exportthư mục con 250 kB trực tiếp từ kho lưu trữ từ xa (có thể có kích thước 200 MB, không bao gồm sửa đổi) - và tôi sẽ chỉ truy cập mạng để chuyển tải xuống 250 kB (hoặc hơn). Với git, archivephải được bật trên máy chủ (vì vậy tôi không thể thử nó) - clone --depth 1từ máy chủ vẫn có thể truy xuất một repo có dung lượng 25 MB, trong đó .gitmột mình thư mục con mất 15 MB . Do đó, tôi vẫn nói câu trả lời là "không".
sdaau

@mrTom câu trả lời là trên thực tế Xem câu trả lời của OP - lệnh làgit checkout-index
nocache

Đây là một cách hay và đơn giản:git archive -o latest.zip HEAD
Evgeni Sergeev

Câu trả lời:


2397

Có lẽ cách đơn giản nhất để đạt được điều này là với git archive. Nếu bạn thực sự cần chỉ cây mở rộng, bạn có thể làm một cái gì đó như thế này.

git archive master | tar -x -C /somewhere/else

Hầu hết thời gian tôi cần 'xuất' thứ gì đó từ git, tôi muốn có một kho lưu trữ nén trong mọi trường hợp vì vậy tôi làm một cái gì đó như thế này.

git archive master | bzip2 >source-tree.tar.bz2

Lưu trữ ZIP:

git archive --format zip --output /full/path/to/zipfile.zip master 

git help archive để biết thêm chi tiết, nó khá linh hoạt.


Xin lưu ý rằng mặc dù kho lưu trữ sẽ không chứa thư mục .git, tuy nhiên, nó sẽ chứa các tệp cụ thể git ẩn khác như .gitignore, .gitattribut, v.v. Nếu bạn không muốn chúng trong kho lưu trữ, hãy đảm bảo bạn sử dụng thuộc tính xuất khẩu bỏ qua trong tệp .gitattribut và cam kết điều này trước khi thực hiện lưu trữ của bạn. Đọc thêm...


Lưu ý: Nếu bạn quan tâm đến việc xuất chỉ mục, lệnh là

git checkout-index -a -f --prefix=/destination/path/

(Xem câu trả lời của Greg để biết thêm chi tiết)


198
Lưu trữ ZIP:git archive --format zip --output /full/path master
Vadim

221
Xin lưu ý rằng kho lưu trữ sẽ không chứa thư mục .git, nhưng sẽ chứa các tệp cụ thể git ẩn khác như .gitignore, .gitattribut, v.v. Vì vậy, nếu bạn không muốn chúng, hãy đảm bảo bạn sử dụng thuộc tính xuất khẩu trong một tập tin .gitattribution và cam kết điều này trước khi thực hiện lưu trữ của bạn. Xem cho ăn.cloud.geek.nz / 2010/02 / từ
mj1531

54
Để theo dõi ghi chú của Luồng: bạn có thể thêm chuỗi '--prefix = Something /' vào lệnh để kiểm soát tên thư mục sẽ được đóng gói bên trong zip. Ví dụ: nếu bạn sử dụng git archive --format zip --output /path/to/file.zip --prefix=newdir/ masterđầu ra sẽ được gọi là 'file.zip' nhưng khi bạn giải nén nó, thư mục cấp cao nhất sẽ là 'newdir'. (Nếu bạn bỏ qua thuộc tính --prefix, thư mục cấp cao nhất sẽ là 'tệp'.)
Alan W. Smith

89
Cách dễ nhất: git archive -o latest.zip HEADNó tạo một kho lưu trữ Zip chứa nội dung của cam kết mới nhất trên nhánh hiện tại. Lưu ý rằng định dạng đầu ra được suy ra bởi phần mở rộng của tệp đầu ra.
nacho4d

37
Nó không hỗ trợ các mô đun con git :(
umpirsky

320

Tôi tìm ra tùy chọn 2 có nghĩa là gì. Từ một kho lưu trữ, bạn có thể làm:

git checkout-index -a -f --prefix=/destination/path/

Dấu gạch chéo ở cuối đường dẫn rất quan trọng, nếu không, nó sẽ dẫn đến các tệp nằm trong / đích với tiền tố là 'đường dẫn'.

Vì trong một tình huống bình thường, chỉ mục chứa nội dung của kho lưu trữ, không có gì đặc biệt để "đọc cây mong muốn vào chỉ mục". Nó đã ở đó rồi.

Các -acờ được yêu cầu phải kiểm tra tất cả các file trong chỉ mục (Tôi không chắc chắn những gì nó có nghĩa là bỏ qua lá cờ này trong tình huống này, vì nó không làm những gì tôi muốn). Các -flực lượng cờ ghi đè lên bất kỳ tập tin hiện có trong đầu ra, mà lệnh này thường không làm.

Đây dường như là loại "xuất khẩu git" mà tôi đang tìm kiếm.


73
... và đừng quên Slash AT THE END, hoặc bạn sẽ không có hiệu quả mong muốn;)
Conny

1
Các git addlệnh thay đổi nội dung trong chỉ mục, vì vậy bất cứ git statuschương trình như "được cam kết" là sự khác biệt giữa đầu và các nội dung của chỉ số.
Greg Hewgill

7
@conny: đọc bình luận của bạn, quên nó đi và chạy lệnh mà không có dấu gạch chéo. mẹo: làm theo lời khuyên của Conny -.-
Znarkus

35
+1 cho lời khuyên của Conny. Ngoài ra, đừng cố tạo '~ / Dest /', vì điều này sẽ tạo một thư mục có tên '~' trong thư mục làm việc của bạn, thay vì những gì bạn thực sự muốn. Đoán xem điều gì sẽ xảy ra khi bạn gõ rm -rf ~
Kyle Heironimus

5
@KyleHeironimus - cảnh báo của bạn về việc sử dụng '~ / Dest / `là đúng nếu bạn sử dụng dấu ngoặc kép quanh đường dẫn tiền tố của bạn để báo cho trình bao không thực hiện mở rộng dấu ngã. Một thư mục được gọi ~(không '~'!) Sẽ được tạo trong thư mục làm việc của bạn. Không có gì đặc biệt về git checkout-indexvấn đề này: Điều tương tự cũng đúng mkdir '~/dest'( đừng làm vậy! ). Tuy nhiên, một lý do chính đáng khác để tránh các tên tệp cần trích dẫn (ví dụ: có một khoảng trắng trong đó) :-)
Matt Wallis

254

git archive cũng hoạt động với kho lưu trữ từ xa.

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master | tar -xf -

Để xuất đường dẫn cụ thể bên trong repo, hãy thêm bao nhiêu đường dẫn bạn muốn như đối số cuối cùng vào git, ví dụ:

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master path1/ path2/ | tar -xv

6
Đây là tùy chọn tôi thích nhất. Nó có lợi ích bổ sung mà nó cũng hoạt động trên các kho lưu trữ trần.
innaM

5
Phiên bản cải tiến là: git archive --format=tar --prefix=PROJECT_NAME/ --remote=USER@SERVER:PROJECT_NAME.git master | tar -xf - (đảm bảo kho lưu trữ của bạn nằm trong một thư mục)
Nick

7
Lưu ý : máy chủ phải kích hoạt tính năng này.
Jakub Narębski

12
Tôi đã thử: git archive --format=zip --output foo.zip --remote=https://github.com/xxx.git masterVà đã gây tử vong: Hoạt động không được hỗ trợ bởi giao thức. Kết thúc bất ngờ của dòng lệnh.
andyf

7
@andyf GitHub có cách riêng của mình: curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -theo tài liệu
giám mục

62

nhập mô tả hình ảnh ở đây

Một câu trả lời trường hợp đặc biệt nếu kho lưu trữ được lưu trữ trên GitHub.

Chỉ cần sử dụng svn export.

Theo như tôi biết thì Github không cho phép archive --remote. Mặc dù GitHub tương thích với svn và chúng có tất cả các repos git svncó thể truy cập để bạn có thể sử dụng svn exportnhư bình thường với một vài điều chỉnh cho url GitHub của bạn.

Ví dụ: để xuất toàn bộ kho lưu trữ, hãy chú ý cách trunkthay thế URL master(hoặc bất cứ điều gì mà nhánh CHÍNH của dự án được đặt thành ):

svn export https://github.com/username/repo-name/trunk/

Và bạn có thể xuất một tệp hoặc thậm chí một đường dẫn hoặc thư mục nhất định:

svn export https://github.com/username/repo-name/trunk/src/lib/folder

Ví dụ với Thư viện JavaScript jQuery

Các HEADchi nhánh hoặc thạc sĩ ngành sẽ sử dụng có sẵn trunk:

svn ls https://github.com/jquery/jquery/trunk

Các HEAD chi nhánh sẽ không truy cập được theo /branches/:

svn ls https://github.com/jquery/jquery/branches/2.1-stable

Tất cả các thẻ theo /tags/cùng một cách:

svn ls https://github.com/jquery/jquery/tags/2.1.3

1
git archivehoạt động tốt với GitHub, miễn là bạn sử dụng giao thức git, chỉ cần thay thế https://bằng git://URL. Tôi không biết tại sao GitHub không quảng cáo tính năng ẩn này.
Neil Mayhew

1
@NeilMayhew Nó không hoạt động với tôi, tôi nhận được fatal: The remote end hung up unexpectedly. Đã thử trên hai máy chủ khác nhau với repo jQuery github.
Anthony Hatzopoulos

Bạn đúng. Tôi đã quên rằng tôi đang sử dụng git config url.<base>.insteadOfđể lưu trữ kho lưu trữ từ xa. Do đó, tôi đã sử dụng một file://URL trong thực tế. Tôi nghi ngờ điều đó git archivecó thể làm việc với git://các URL vì nó cần có khả năng chạy git-upload-archiveở đầu xa. Có thể sử dụng sshgiao thức, ngoại trừ việc github không cho phép nó ( Invalid command: 'git-upload-archive').
Neil Mayhew

Bất kỳ cách nào để sử dụng một công cụ máy chủ cục bộ hoạt động như github nếu tôi muốn làm điều đó trên kho git được lưu trữ nội bộ?
kriss

1
được nâng cấp - thật kỳ lạ khi Git không có tính năng này và chúng tôi phải dùng đến svn
Jason S

40

Từ Hướng dẫn sử dụng Git :

Sử dụng git-checkout-index để "xuất toàn bộ cây"

Khả năng tiền tố về cơ bản làm cho nó trở nên tầm thường khi sử dụng chỉ số git-checkout-index như một hàm "xuất dưới dạng cây". Chỉ cần đọc cây mong muốn vào chỉ mục và làm:

$ git checkout-index --prefix=git-export-dir/ -a


19
Tôi nghĩ rằng sự nhầm lẫn là cụm từ "đọc cây mong muốn vào chỉ mục".
davetron5000

4
Nếu bạn muốn xuất thư mục foo trong thanh nhánh, thì đây sẽ là git read-tree bar:foogit checkout-index --prefix=export_dir/ -asau đó có lẽ bạn nên làmgit update-index master
Pascal Rosin

1
@JohnWeldon Nó có yêu cầu bạn sao chép repo trước không? Nếu vậy, thì tôi sẽ không chấp nhận nó, vì toàn bộ quan điểm "xuất khẩu svn" của thư mục con là trực tiếp lấy một bản sao của thư mục con đó; nếu ai đó có repo Git 1GB và tất cả những gì tôi muốn là thư mục con 10kB, thật điên rồ khi yêu cầu tôi sao chép toàn bộ.
Jason S

3
Ngoài ra tôi sẽ lặp lại @ davetron5000 với lời bình luận "đọc cây mong muốn vào chỉ mục" mà tôi không biết ý nghĩa của nó là gì.
Jason S

38

Tôi đã viết một trình bao bọc đơn giản xung quanh git-checkout-indexmà bạn có thể sử dụng như thế này:

git export ~/the/destination/dir

Nếu thư mục đích đã tồn tại, bạn sẽ cần thêm -fhoặc --force.

Cài đặt đơn giản; chỉ cần bỏ tập lệnh ở đâu đó trong bạn PATHvà đảm bảo nó có thể thực thi được.

Kho github cho git-export


15
Trình bao bọc này không phải là nền tảng bất khả tri; nó dựa vào / bin / sh. Vì vậy, nếu bạn đang dùng Windows, giải pháp này có thể sẽ không hiệu quả với bạn.
shovavnik

18
Uhh, tập lệnh này là 57 dòng tài liệu, khoảng trắng, thiết lập, phân tích cú pháp đối số và chỉ có một dòng thực sự làm gì đó ...
Vladimir Panteleev

36

Có vẻ như đây không phải là vấn đề với Git so với SVN. Git chỉ đặt thư mục .git trong thư mục gốc của kho lưu trữ, trong khi SVN đặt thư mục .svn trong mọi thư mục con. Vì vậy, "xuất svn" tránh ma thuật dòng lệnh đệ quy, trong khi với đệ quy Git là không cần thiết.


26
Kể từ SVN 1.7, cũng chỉ có một thư mục .svn: subversion.apache.org/docs/release-notes/1.7.html#single-db
kostmo

Điều này sẽ không loại bỏ bất kỳ tệp xây dựng bổ sung nào mà svn xuất xóa. Vì vậy, đây chắc chắn không phải là câu trả lời.
ygoe

28

Tương đương với

svn export . otherpath

bên trong một repo hiện có là

git archive branchname | (cd otherpath; tar x)

Tương đương với

svn export url otherpath

git archive --remote=url branchname | (cd otherpath; tar x)

1
cảm ơn, đây là thứ tôi đã thiếu ... ngoài ra, để kiểm tra dấu thời gian của bản xuất (chúng sẽ không được lưu giữ như trên tệp), sử dụng git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -)... Tuy nhiên, lưu trữ với dấu thời gian không chính xác, vì vậy tôi đã đăng một ví dụ dưới đây .
sdaau

1
Bạn có thể sử dụng tùy chọn C cho tar thay vì subshell, như thế này: git archive branchname | tar xC otherpath
James Moore

Nhận thấy rằng Ctùy chọn cho tar chỉ là GNU Tar.
aredridel

22

Nếu bạn không loại trừ các tệp với .gitattributes export-ignorethì hãy thửgit checkout

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout -f -q

-f
Khi kiểm tra các đường dẫn từ chỉ mục, không thất bại khi các mục không được trộn; thay vào đó, các mục không được trộn được bỏ qua.

-q
Tránh dài dòng

Ngoài ra, bạn có thể nhận được bất kỳ Chi nhánh hoặc Thẻ hoặc từ Sửa đổi Cam kết cụ thể như trong SVN chỉ cần thêm SHA1 (SHA1 trong Git tương đương với Số sửa đổi trong SVN)

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout 2ef2e1f2de5f3d4f5e87df7d8 -f -q -- ./

Các /path/to/checkout/phải trống, Git sẽ không xóa bất kỳ tập tin, nhưng sẽ ghi đè lên các file có cùng tên mà không có cảnh báo nào

CẬP NHẬT: Để tránh sự cố bị chặt đầu hoặc để nguyên vẹn kho lưu trữ đang hoạt động khi sử dụng thanh toán để xuất với thẻ, nhánh hoặc SHA1, bạn cần thêm -- ./vào cuối

Dấu gạch ngang đôi --cho git biết rằng mọi thứ sau dấu gạch ngang là đường dẫn hoặc tệp và trong trường hợp này cũng bảo git checkoutkhông thay đổiHEAD

Ví dụ:

Lệnh này sẽ chỉ nhận thư mục libs và readme.txttập tin từ đó cam kết chính xác

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt

Điều này sẽ tạo ra (ghi đè) my_file_2_behind_HEAD.txthai cam kết phía sau đầuHEAD^2

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout HEAD^2 -f -q -- ./my_file_2_behind_HEAD.txt

Để có được xuất khẩu của một chi nhánh khác

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./

Lưu ý rằng ./có liên quan đến thư mục gốc của kho lưu trữ


Trên thực tế, trong số rất nhiều người khác và upvote, điều này làm việc tốt nhất đối với tôi, không có bất kỳ sự nén nào, hoạt động tốt với các kho lưu trữ trần (gitolite).
takeshin

1
Lưu ý rằng thanh toán SHA1 sẽ tạo ra sự cố "chặt đầu" trong kho lưu trữ
user5286776117878

thực tế @ITGabs, điều này không tải xuống thư mục ".git". Vì vậy, thư mục đã tải xuống không phải là kho lưu trữ git, vì vậy nó không bị "chặt đầu" về mặt kỹ thuật
Fabio Marreco

@FabioMarreco Vấn đề chặt đầu nằm ở kho lưu trữ không có trong các tệp được xuất / tải xuống, tôi đang cập nhật câu trả lời để biết thêm chi tiết
user5286776117878

3
Nó hiệu quả tuyệt vời đối với tôi. Nhưng lúc đầu, tôi nhận được thông báo lỗi "Không phải là kho git". Sau đó, tôi thấy rằng "/ path / to / repo /" phải trỏ đến thư mục .git. Vì vậy, điều này đã làm việc: --git-dir = / path / to / repo / .git
philburk

21

Tôi sử dụng git-subodules rộng rãi. Cái này hoạt động với tôi:

rsync -a ./FROM/ ./TO --exclude='.*'

1
Sẽ không bỏ lỡ các tệp có tên bắt đầu bằng dấu chấm, chẳng hạn như .htaccess?
Greg Hewgill

8
Một giải pháp tốt, tôi sẽ thay đổi --exclude = '. *' Thành --exclude = '.
Git

18
--exclude-vcs nếu bạn đang đi để có sự khéo léo này
plod

./FROM/ có thể là một repo từ xa không?
Chống lại thiết kế

2
Là một FYI, bản sao của tôi rsyncliệt kê các đối số là --cvs-exclude. Ngoài ra, nó vẫn sao chép .gitattributes.gitignore
Ryan Ransford

19

Tôi đã truy cập trang này thường xuyên khi tìm cách xuất kho git. Câu trả lời của tôi cho câu hỏi này xem xét ba thuộc tính mà svn xuất có theo thiết kế so với git, vì svn tuân theo cách tiếp cận kho lưu trữ tập trung:

  • Nó giảm thiểu lưu lượng truy cập đến một vị trí kho lưu trữ từ xa bằng cách không xuất tất cả các sửa đổi
  • Nó không bao gồm thông tin meta trong thư mục xuất
  • Xuất một nhánh nhất định bằng svn được thực hiện bằng cách chỉ định đường dẫn thích hợp

    git clone --depth 1 --branch master git://git.somewhere destination_path
    rm -rf destination_path/.git
    

Khi xây dựng một bản phát hành nhất định, rất hữu ích để sao chép một nhánh ổn định như ví dụ --branch stablehoặc --branch release/0.9.


Điều này không hoạt động nếu đích đến tồn tại và không trống.
Eponymous

2
Câu trả lời đúng: nó phát sinh từ sâu thẳm. Cách git archive | tartiếp cận không thể áp dụng được với các môi trường hệ vỏ không tương thích POSIX (ví dụ, CI dựa trên CMD- hoặc PowerShell của AppVeyor), không lý tưởng. Cách git checkouttiếp cận sửa đổi chỉ số của cây làm việc chính, đó là khủng khiếp. Cách git checkout-indextiếp cận đòi hỏi chỉ số của cây làm việc chính phải được sửa đổi trước, điều này thậm chí còn khủng khiếp. Cách git clonetiếp cận truyền thống nhân bản toàn bộ lịch sử của kho lưu trữ trước khi xóa lịch sử đó, điều này thật lãng phí. Đây là giải pháp lành mạnh duy nhất còn lại.
Cecil Curry

1
Để xuất cục bộ, lưu ý rằng đường dẫn tuyệt đối của cây làm việc Git được sao chép từ nên được tiền tố bởi file://giao thức (ví dụ git clone --depth 1 --branch v3.14.15 file:///home/me/src_repo trg_repo:). Không làm như vậy sẽ phát ra "warning: --depth is ignored in local clones; use file:// instead."và thực hiện một tiêu chuẩn chứ không phải là bản sao nông, đánh bại toàn bộ mục đích của câu trả lời này. Salud!
Cecil Curry

16

Điều này sẽ sao chép tất cả nội dung, trừ các tệp .dot. Tôi sử dụng điều này để xuất các dự án nhân bản git vào repo git của ứng dụng web của tôi mà không có công cụ .git.

cp -R ./path-to-git-repo / đường dẫn / đến / đích /

Đồng bằng cũ bash hoạt động chỉ là tuyệt vời :)


Tại sao không chỉ đẩy đến từ xa? Thậm chí đơn giản hơn bash.
Nurettin

2
Còn các tệp là một phần của ứng dụng web và tên của nó bắt đầu bằng dấu chấm thì sao? :) nghĩ về .htaccess
Artur

3
Đôi khi bạn cũng muốn bỏ qua những gì trong .gitignore, điều này sẽ không.
fregante

14

Đơn giản như sao chép rồi xóa thư mục .git:

git clone url_of_your_repo path_to_export && rm -rf path_to_export/.git


4
Thành thật mà nói - câu trả lời này, cũng là số 1 trong câu hỏi - là những gì bạn sẽ làm 99% thời gian. Hầu hết các câu trả lời là điên quá mức.
Geoff Nixon

11

Đối với người dùng GitHub, git archive --remotephương thức này sẽ không hoạt động trực tiếp, vì URL xuất là không lâu . Bạn phải hỏi GitHub cho URL, sau đó tải xuống URL đó. curllàm cho nó dễ dàng

curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -

Điều này sẽ cung cấp cho bạn mã xuất trong một thư mục địa phương. Thí dụ:

$ curl -L https://api.github.com/repos/jpic/bashworks/tarball | tar xzf -
$ ls jpic-bashworks-34f4441/
break  conf  docs  hack  LICENSE  mlog  module  mpd  mtests  os  README.rst  remote  todo  vcs  vps  wepcrack

Chỉnh sửa
Nếu bạn muốn mã được đặt vào một thư mục cụ thể, hiện có (chứ không phải là ngẫu nhiên từ github):

curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | \
tar xzC /path/you/want --strip 1

11

Có, đây là một lệnh gọn gàng và gọn gàng để lưu trữ mã của bạn mà không có bất kỳ sự bao gồm git nào trong kho lưu trữ và rất tốt để vượt qua mà không phải lo lắng về bất kỳ lịch sử cam kết git nào.

git archive --format zip --output /full/path/to/zipfile.zip master 

Điều này thật tuyệt, chỉ cần xóa gitignore sau và nó đã được thực hiện và sẵn sàng để chia sẻ.
Sogger

Loại bỏ .gitgnore vv được nêu trong ý kiến trả lời được chấp nhận: sử dụng .gitattributes tập tin, xem feeding.cloud.geek.nz/posts/excluding-files-from-git-archive
Sogger

10

Tôi chỉ muốn chỉ ra rằng trong trường hợp bạn là

  1. xuất một thư mục con của kho lưu trữ (đó là cách tôi đã sử dụng để sử dụng tính năng xuất SVN)
  2. Được sao chép mọi thứ từ thư mục đó đến đích triển khai
  3. và vì bạn đã có một bản sao của toàn bộ kho lưu trữ.

Sau đó, bạn chỉ có thể sử dụng cp foo [destination]thay vì được đề cập git-archive master foo | -x -C [destination].


9

Bạn có thể lưu trữ một repo từ xa tại bất kỳ cam kết nào dưới dạng tệp zip.

git archive --format=zip --output=archive.zip --remote=USERNAME@HOSTNAME:PROJECTNAME.git HASHOFGITCOMMIT

8

Bash-thực hiện xuất khẩu git.

Tôi đã phân đoạn các quá trình tạo và xóa tệp .empty trên chức năng riêng của họ, với mục đích sử dụng lại chúng trong triển khai 'git-archive' (sẽ được đăng sau).

Tôi cũng đã thêm tệp '.gitattribut' vào quy trình để xóa các tệp không mong muốn khỏi thư mục xuất khẩu đích. Bao gồm tính chi tiết cho quy trình trong khi làm cho chức năng 'git-export' hiệu quả hơn.

EMPTY_FILE = ". Trống";

function create_empty () {
## Processing path (target-dir):
    TRG_PATH="${1}";
## Component(s):
    EXCLUDE_DIR=".git";
echo -en "\nAdding '${EMPTY_FILE}' files to empty folder(s): ...";
    find ${TRG_PATH} -not -path "*/${EXCLUDE_DIR}/*" -type d -empty -exec touch {}/${EMPTY_FILE} \;
#echo "done.";
## Purging SRC/TRG_DIRs variable(s):
    unset TRG_PATH EMPTY_FILE EXCLUDE_DIR;
    return 0;
  }

declare -a GIT_EXCLUDE;
function load_exclude () {
    SRC_PATH="${1}";
    ITEMS=0; while read LINE; do
#      echo -e "Line [${ITEMS}]: '${LINE%%\ *}'";
      GIT_EXCLUDE[((ITEMS++))]=${LINE%%\ *};
    done < ${SRC_PATH}/.gitattributes;
    GIT_EXCLUDE[${ITEMS}]="${EMPTY_FILE}";
## Purging variable(s):
    unset SRC_PATH ITEMS;
    return 0;
  }

function purge_empty () {
## Processing path (Source/Target-dir):
    SRC_PATH="${1}";
    TRG_PATH="${2}";
echo -e "\nPurging Git-Specific component(s): ... ";
    find ${SRC_PATH} -type f -name ${EMPTY_FILE} -exec /bin/rm '{}' \;
    for xRULE in ${GIT_EXCLUDE[@]}; do
echo -en "    '${TRG_PATH}/{${xRULE}}' files ... ";
      find ${TRG_PATH} -type f -name "${xRULE}" -exec /bin/rm -rf '{}' \;
echo "done.'";
    done;
echo -e "done.\n"
## Purging SRC/TRG_PATHs variable(s):
    unset SRC_PATH; unset TRG_PATH;
    return 0;
  }

function git-export () {
    TRG_DIR="${1}"; SRC_DIR="${2}";
    if [ -z "${SRC_DIR}" ]; then SRC_DIR="${PWD}"; fi
    load_exclude "${SRC_DIR}";
## Dynamically added '.empty' files to the Git-Structure:
    create_empty "${SRC_DIR}";
    GIT_COMMIT="Including '${EMPTY_FILE}' files into Git-Index container."; #echo -e "\n${GIT_COMMIT}";
    git add .; git commit --quiet --all --verbose --message "${GIT_COMMIT}";
    if [ "${?}" -eq 0 ]; then echo " done."; fi
    /bin/rm -rf ${TRG_DIR} && mkdir -p "${TRG_DIR}";
echo -en "\nChecking-Out Index component(s): ... ";
    git checkout-index --prefix=${TRG_DIR}/ -q -f -a
## Reset: --mixed = reset HEAD and index:
    if [ "${?}" -eq 0 ]; then
echo "done."; echo -en "Resetting HEAD and Index: ... ";
        git reset --soft HEAD^;
        if [ "${?}" -eq 0 ]; then
echo "done.";
## Purging Git-specific components and '.empty' files from Target-Dir:
            purge_empty "${SRC_DIR}" "${TRG_DIR}"
          else echo "failed.";
        fi
## Archiving exported-content:
echo -en "Archiving Checked-Out component(s): ... ";
        if [ -f "${TRG_DIR}.tgz" ]; then /bin/rm ${TRG_DIR}.tgz; fi
        cd ${TRG_DIR} && tar -czf ${TRG_DIR}.tgz ./; cd ${SRC_DIR}
echo "done.";
## Listing *.tgz file attributes:
## Warning: Un-TAR this file to a specific directory:
        ls -al ${TRG_DIR}.tgz
      else echo "failed.";
    fi
## Purgin all references to Un-Staged File(s):
   git reset HEAD;
## Purging SRC/TRG_DIRs variable(s):
    unset SRC_DIR; unset TRG_DIR;
    echo "";
    return 0;
  }

Đầu ra:

$ git-export /tmp/rel-1.0.0

Thêm tệp '.empty' vào (các) thư mục trống: ... đã xong.

Thành phần chỉ mục kiểm tra: ... đã xong.

Đặt lại ĐẦU và Chỉ mục: ... xong.

Purging Thành phần cụ thể Git: ...

'/tmp/rel-1.0.0/ đũa.buildpath}' đã hoàn tất. '

'/tmp/rel-1.0.0/ đũa.project}' tập tin ... đã xong. '

'/tmp/rel-1.0.0/ đũa.gitignore}' đã hoàn tất. '

Các tập tin '/tmp/rel-1.0.0/ đũa.git}' ... đã xong. '

'/tmp/rel-1.0.0/ đũa.gitattribut}' tập tin ... đã xong. '

Các tập tin '/tmp/rel-1.0.0/ đũa*.mno}' ... đã xong. '

'/tmp/rel-1.0.0/ đũa * ~}' đã hoàn tất. '

'/tmp/rel-1.0.0/ đũa.*~}' tập tin ... đã xong. '

'/tmp/rel-1.0.0/ đũa*.swp}' đã hoàn tất. '

'/tmp/rel-1.0.0/ đũa*.swo}' đã hoàn tất. '

'/tmp/rel-1.0.0/ đũa.DS_Store}' tập tin ... đã xong. '

'/tmp/rel-1.0.0/ đũa.sinstall}' đã hoàn tất. '

Các tập tin '/tmp/rel-1.0.0/ đũa.empty}' ... đã xong. '

làm xong.

Lưu trữ thành phần đã kiểm tra (s): ... xong.

-rw-r - r-- 1 bánh xe quản trị viên 25445901 3 tháng 12 12:57 /tmp/rel-1.0.0.tgz

Bây giờ tôi đã kết hợp chức năng 'git archive' vào một quy trình duy nhất sử dụng chức năng 'create_empty' và các tính năng khác.

function git-archive () {
    PREFIX="${1}"; ## sudo mkdir -p ${PREFIX}
    REPO_PATH="`echo "${2}"|awk -F: '{print $1}'`";
    RELEASE="`echo "${2}"|awk -F: '{print $2}'`";
    USER_PATH="${PWD}";
echo "$PREFIX $REPO_PATH $RELEASE $USER_PATH";
## Dynamically added '.empty' files to the Git-Structure:
    cd "${REPO_PATH}"; populate_empty .; echo -en "\n";
#    git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0
# e.g.: git-archive /var/www/htdocs /repos/domain.name/website:rel-1.0.0 --explode
    OUTPUT_FILE="${USER_PATH}/${RELEASE}.tar.gz";
    git archive --verbose --prefix=${PREFIX}/ -o ${OUTPUT_FILE} ${RELEASE}
    cd "${USER_PATH}";
    if [[ "${3}" =~ [--explode] ]]; then
      if [ -d "./${RELEASE}" ]; then /bin/rm -rf "./${RELEASE}"; fi
      mkdir -p ./${RELEASE}; tar -xzf "${OUTPUT_FILE}" -C ./${RELEASE}
    fi
## Purging SRC/TRG_DIRs variable(s):
    unset PREFIX REPO_PATH RELEASE USER_PATH OUTPUT_FILE;
    return 0;
  }

Cách sử dụng: git-archive [/ var / www / htdocs] /repose/web.domain/website:rel-1.0.0
tocororo

8

Nếu bạn muốn một cái gì đó hoạt động với mô hình con, điều này có thể đáng để đi.

Ghi chú:

  • MASTER_DIR = kiểm tra với các mô hình con của bạn cũng được kiểm tra
  • DEST_DIR = nơi xuất khẩu này sẽ kết thúc
  • Nếu bạn có rsync, tôi nghĩ bạn có thể làm điều tương tự với ít đau hơn.

Giả định:

  • Bạn cần chạy cái này từ thư mục mẹ của MASTER_DIR (tức là từ MASTER_DIR cd ..)
  • DEST_DIR được coi là đã được tạo. Điều này khá dễ dàng để sửa đổi để bao gồm việc tạo DEST_DIR nếu bạn muốn

cd MASTER_DIR && tar -zcvf ../DEST_DIR/export.tar.gz --exclude = '. git *'. && cd ../DEST_DIR/ && tar xvfz export.tar.gz && rm export.tar.gz


6

Sở thích của tôi thực sự sẽ có một quận mục tiêu trong Makefile của bạn (hoặc hệ thống xây dựng khác) rằng xuất khẩu một kho lưu trữ chia mã của bạn (.tar.bz2, .zip, .jar, hoặc bất cứ điều gì là thích hợp). Nếu bạn tình cờ sử dụng GNU autotools hoặc các hệ thống MakeMaker của Perl, tôi nghĩ rằng điều này tự động tồn tại cho bạn. Nếu không, tôi khuyên bạn nên thêm nó.

ETA (2012-09-06): Wow, downvote khắc nghiệt. Tôi vẫn tin rằng tốt hơn là xây dựng các bản phân phối của mình bằng các công cụ xây dựng thay vì công cụ kiểm soát mã nguồn của bạn. Tôi tin vào việc xây dựng các đồ tạo tác với các công cụ xây dựng. Trong công việc hiện tại của tôi, sản phẩm chính của chúng tôi được xây dựng với mục tiêu là kiến. Chúng tôi đang ở giữa việc chuyển đổi các hệ thống kiểm soát mã nguồn và sự hiện diện của mục tiêu kiến ​​này có nghĩa là ít gặp rắc rối hơn trong việc di chuyển.


Dự án tôi có trong đầu không phải là một dự án mã; nó xảy ra nhiều hơn trong các dự án trang web.
Greg Hewgill

Không giải quyết câu hỏi.
Andrew Ferrier

1
Vâng, một câu trả lời như vậy có thể không phù hợp với nhu cầu của mọi người, nhưng các downvote rất kỳ quái. Đó một câu trả lời hoàn toàn hợp lệ, và thực sự, trong nhiều tình huống, câu trả lời đúng duy nhất. Nó làm cho điểm rất hợp lệ rằng suy nghĩ về vấn đề này như là một "vấn đề công cụ vc" thường đi sai đường hoàn toàn.
snogglethorpe

6

Điều này sẽ sao chép các tệp trong một phạm vi cam kết (C đến G) sang một tệp tar. Lưu ý: điều này sẽ chỉ nhận được các tập tin cam kết. Không phải toàn bộ kho lưu trữ. Sửa đổi một chút từ đây

Ví dụ về lịch sử cam kết

A -> B -> C -> D -> E -> F -> G -> H -> I

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT C~..G | xargs tar -rf myTarFile.tar

Trang hướng dẫn sử dụng git-diff-tree

-r -> tái diễn thành cây con

--no-commit-id -> git diff-tree xuất ra một dòng có ID xác nhận khi áp dụng. Cờ này đã chặn đầu ra ID cam kết.

--name-only -> Chỉ hiển thị tên của các tệp đã thay đổi.

--diff-filter = ACMRT -> Chỉ chọn những tệp này. Xem ở đây để xem danh sách đầy đủ các tập tin

C..G -> Tệp trong phạm vi cam kết này

C ~ -> Bao gồm các tệp từ Commit C. Không chỉ các tệp kể từ Commit C.

| xargs tar -rf myTarFile -> xuất ra tar


5

Theo tôi hiểu câu hỏi, nó chỉ nói về việc tải xuống một số trạng thái nhất định từ máy chủ, không có lịch sử và không có dữ liệu của các nhánh khác, thay vì trích xuất một trạng thái từ kho lưu trữ cục bộ (như nhiều anwers ở đây làm).

Điều đó có thể được thực hiện như thế này:

git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \
&& rm -rf repo/.git/
  • --single-branch có sẵn kể từ Git 1.7.10 (tháng 4 năm 2012).
  • --depthlà (đã?) được báo cáo là bị lỗi, nhưng đối với trường hợp xuất khẩu, các vấn đề được đề cập không nên quan trọng.

Lưu ý: Tôi chỉ nhận thấy có 2 trang của anwsers, tôi chỉ xem một trang trước khi đăng. Chỉ có một anwser tương tự --depth, chỉ ngụ ý --single-branchtrừ khi --no-single-branchđược đưa ra, điều đó có nghĩa là điều này có thể có tác dụng tương tự. Không chắc chắn mặc dù, một số chuyên gia có thể xác nhận?
Ondra Žižka

4

Tôi cần điều này cho một kịch bản triển khai và tôi không thể sử dụng bất kỳ phương pháp tiếp cận nào được đề cập ở trên. Thay vào đó tôi tìm ra một giải pháp khác:

#!/bin/sh
[ $# -eq 2 ] || echo "USAGE $0 REPOSITORY DESTINATION" && exit 1
REPOSITORY=$1
DESTINATION=$2
TMPNAME="/tmp/$(basename $REPOSITORY).$$"
git clone $REPOSITORY $TMPNAME
rm -rf $TMPNAME/.git
mkdir -p $DESTINATION
cp -r $TMPNAME/* $DESTINATION
rm -rf $TMPNAME

Vấn đề với giải pháp lưu trữ chỉ mục cây / thanh toán hoặc lưu trữ là gì? Theo như tôi có thể nói bạn đã làm tương đương với một cái gì đó giống như mkdir -p "$2" && git --git-dir="$1" archive HEAD | tar -x -C "$2"nhưng hơi dài dòng hơn.
CB Bailey

1
Tôi không thể có được cây đọc để làm việc từ một kho lưu trữ từ xa và giải pháp lưu trữ không hoạt động với github.
troelskn

Có với kho lưu trữ nhận lệnh Không hợp lệ: 'git-upload-archive' ... và tôi không có tùy chọn cấu hình core.gitProxy và tùy chọn biến môi trường
GIT_PROXY_COMMAND

4

Làm theo cách dễ dàng, đây là một chức năng cho .bash_profile, nó trực tiếp giải nén tệp lưu trữ trên vị trí hiện tại, trước tiên định cấu hình [url: path] thông thường của bạn. LƯU Ý: Với chức năng này, bạn tránh được thao tác sao chép, nó được lấy trực tiếp từ repo từ xa.

gitss() {
    URL=[url:path]

    TMPFILE="`/bin/tempfile`"
    if [ "$1" = "" ]; then
        echo -e "Use: gitss repo [tree/commit]\n"
        return
    fi
    if [ "$2" = "" ]; then
        TREEISH="HEAD"
    else
        TREEISH="$2"
    fi
    echo "Getting $1/$TREEISH..."
    git archive --format=zip --remote=$URL/$1 $TREEISH > $TMPFILE && unzip $TMPFILE && echo -e "\nDone\n"
    rm $TMPFILE
}

Bí danh cho .gitconfig, yêu cầu cấu hình tương tự (Taken CARE thực thi lệnh bên trong các dự án .git, LUÔN LUÔN nhảy đến thư mục cơ sở trước đây như đã nói ở đây , cho đến khi điều này được khắc phục, cá nhân tôi thích chức năng này

ss = !env GIT_TMPFILE="`/bin/tempfile`" sh -c 'git archive --format=zip --remote=[url:path]/$1 $2 \ > $GIT_TMPFILE && unzip $GIT_TMPFILE && rm $GIT_TMPFILE' -

4

Cho đến nay, cách dễ nhất tôi từng thấy để làm điều đó (và cũng hoạt động trên windows) là git bundle:

git bundle create /some/bundle/path.bundle --all

Xem câu trả lời này để biết thêm chi tiết: Làm cách nào tôi có thể sao chép kho git của mình từ máy windows sang máy linux qua ổ đĩa USB?


git bundlebao gồm .gitthư mục, đó là điều mà OP không muốn; git archivecó vẻ là cách thích hợp hơn
ssc

Tài liệu về công --alltắc ở đâu?
Garret Wilson

4

Tôi có một giải pháp khác hoạt động tốt nếu bạn có một bản sao cục bộ của kho lưu trữ trên máy nơi bạn muốn tạo bản xuất. Trong trường hợp này di chuyển đến thư mục kho lưu trữ này và nhập lệnh này:

GIT_WORK_TREE=outputdirectory git checkout -f

Điều này đặc biệt hữu ích nếu bạn quản lý một trang web có kho git và muốn kiểm tra phiên bản sạch trong /var/www/. Trong trường hợp này, hãy thêm phần này vào .git/hooks/post-receivetập lệnh ( hooks/post-receivetrên kho lưu trữ trống, phù hợp hơn trong tình huống này)


3

Tôi nghĩ rằng bài đăng của @Aredridel là gần nhất, nhưng có thêm một chút về điều đó - vì vậy tôi sẽ thêm bài này vào đây; điều này là, svnnếu bạn đang ở trong thư mục con của repo và bạn làm:

/media/disk/repo_svn/subdir$ svn export . /media/disk2/repo_svn_B/subdir

sau đó svnsẽ xuất tất cả các tệp nằm dưới sự kiểm soát sửa đổi (chúng cũng có thể được thêm mới; hoặc trạng thái đã sửa đổi) - và nếu bạn có "rác" khác trong thư mục đó (và tôi không đếm các .svnthư mục con ở đây, nhưng có thể nhìn thấy .ocác tệp như tệp) , nó sẽ không được xuất khẩu; chỉ những tệp được đăng ký bởi repo SVN mới được xuất. Đối với tôi, một điều tuyệt vời là việc xuất này cũng bao gồm các tệp có thay đổi cục bộ chưa được cam kết; và một điều tuyệt vời nữa là dấu thời gian của các tệp được xuất giống như tệp gốc. Hoặc, như svn help exportđặt nó:

  1. Xuất khẩu một cây thư mục sạch từ bản sao làm việc được chỉ định bởi PATH1, tại REV sửa đổi nếu nó được đưa ra, nếu không thì tại LÀM VIỆC, vào PATH2. ... Nếu REV không được chỉ định, tất cả các thay đổi cục bộ sẽ được giữ nguyên. Các tập tin không thuộc kiểm soát phiên bản sẽ không được sao chép.

Để nhận ra rằng gitsẽ không bảo toàn dấu thời gian, hãy so sánh đầu ra của các lệnh này (trong thư mục con của gitrepo bạn chọn):

/media/disk/git_svn/subdir$ ls -la .

... và:

/media/disk/git_svn/subdir$ git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -)

... Và trong mọi trường hợp, tôi nhận thấy rằng git archivetất cả các dấu thời gian của tệp lưu trữ đều giống nhau! git help archivenói:

git archive hoạt động khác nhau khi được cung cấp ID cây so với khi được cung cấp ID cam kết hoặc ID thẻ. Trong trường hợp đầu tiên, thời gian hiện tại được sử dụng làm thời gian sửa đổi của mỗi tệp trong kho lưu trữ. Trong trường hợp sau, thời gian cam kết như được ghi trong đối tượng cam kết được tham chiếu được sử dụng thay thế.

... nhưng rõ ràng cả hai trường hợp đều đặt "thời gian sửa đổi của mỗi tệp"; do đó không bảo toàn dấu thời gian thực tế của các tệp đó!

Vì vậy, để bảo toàn dấu thời gian, đây là một bashtập lệnh, thực sự là "một lớp", mặc dù hơi phức tạp - vì vậy bên dưới nó được đăng thành nhiều dòng:

/media/disk/git_svn/subdir$ git archive --format=tar master | (tar tf -) | (\
  DEST="/media/diskC/tmp/subdirB"; \
  CWD="$PWD"; \
  while read line; do \
    DN=$(dirname "$line"); BN=$(basename "$line"); \
    SRD="$CWD"; TGD="$DEST"; \
    if [ "$DN" != "." ]; then \
      SRD="$SRD/$DN" ; TGD="$TGD/$DN" ; \
      if [ ! -d "$TGD" ] ; then \
        CMD="mkdir \"$TGD\"; touch -r \"$SRD\" \"$TGD\""; \
        echo "$CMD"; \
        eval "$CMD"; \
      fi; \
    fi; \
    CMD="cp -a \"$SRD/$BN\" \"$TGD/\""; \
    echo "$CMD"; \
    eval "$CMD"; \
    done \
)

Lưu ý rằng giả định rằng bạn đang xuất nội dung trong thư mục "hiện tại" (ở trên /media/disk/git_svn/subdir) - và đích bạn đang xuất vào được đặt hơi bất tiện, nhưng nó nằm trong DESTbiến môi trường. Lưu ý rằng với kịch bản này; bạn phải tự tạo DESTthư mục trước khi chạy đoạn script trên.

Sau khi tập lệnh được chạy, bạn sẽ có thể so sánh:

ls -la /media/disk/git_svn/subdir
ls -la /media/diskC/tmp/subdirB   # DEST

... và hy vọng sẽ thấy các dấu thời gian tương tự (đối với các tệp nằm dưới sự kiểm soát phiên bản).

Hy vọng điều này sẽ giúp ai đó,
Chúc mừng!


3

xuất git vào kho lưu trữ zip trong khi thêm tiền tố (ví dụ: tên thư mục):

git archive master --prefix=directoryWithinZip/  --format=zip -o out.zip


1

tôi có hàm tiện ích sau trong tệp .bashrc của mình: nó tạo ra một kho lưu trữ của nhánh hiện tại trong kho git.

function garchive()
{
  if [[ "x$1" == "x-h" || "x$1" == "x" ]]; then
    cat <<EOF
Usage: garchive <archive-name>
create zip archive of the current branch into <archive-name>
EOF
  else
    local oname=$1
    set -x
    local bname=$(git branch | grep -F "*" | sed -e 's#^*##')
    git archive --format zip --output ${oname} ${bname}
    set +x
  fi
}
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.