Làm cách nào để chuyển đổi kho lưu trữ git trần thành kho lưu trữ bình thường (tại chỗ)?


81

Tôi có một kho lưu trữ git trần, nhưng cần truy cập và duyệt nội dung của nó qua ssh (trong trình quản lý tệp như trải nghiệm người dùng).

Tôi cho rằng tôi có thể sao chép nó:

git clone -l <path_to_bare_repo> <new_normal_repo>

Tuy nhiên, kho lưu trữ của tôi có dung lượng khoảng 20GB và tôi không có dung lượng để sao chép nó. Có cách nào để chuyển đổi kho lưu trữ trống tại chỗ để kết thúc với một bản sao hoạt động trong đó không?


5
Chưa được kiểm tra nhưng nếu bạn di chuyển đặt nội dung của kho lưu trữ trống vào một .gitthư mục và đặt baretham số trong cấu hình thành false, thì nó sẽ hoạt động giống như một kho lưu trữ thông thường, nơi bạn có thể chỉ git checkoutđể lấy tệp của mình.
Noufal Ibrahim

Tùy thuộc vào những gì bạn có nghĩa là bởi "duyệt nội dung của nó", có lẽ bạn có thể làm tất cả mọi thứ bạn muốn trong một repo trần sử dụng git showgit cat-file
William Pursell

Cảm ơn vì gợi ý, hữu ích. Tôi cần một trình quản lý tệp hơn như kinh nghiệm (đã chỉnh sửa câu hỏi).
nyi

Nếu hệ thống tệp của bạn hỗ trợ liên kết cứng và bạn sao chép vào cùng một hệ thống tệp, thì sao chép -l sẽ không chiếm thêm dung lượng đĩa vì nó liên kết cứng tất cả các đối tượng. Tuy nhiên, bạn sẽ cần không gian để thanh toán, như những người khác đã lưu ý.
Neil Mayhew

1
Nếu kho lưu trữ trống của bạn chiếm 20GB dung lượng đĩa, thì cây làm việc sẽ cần thêm bao nhiêu? Bạn có thực sự có nhiều không gian?
ADTC

Câu trả lời:


113

Lưu ý : Tôi đã thử nghiệm điều này trên một kho lưu trữ 1 cam kết rất đơn giản . Kiểm tra kỹ phần này, đọc các trang người dùng và luôn vui mừng vì bạn đã sao lưu trước khi làm theo lời khuyên bạn tìm thấy trên StackOverflow. (Bạn sao lưu, phải không?)

Để chuyển đổi một --barekho lưu trữ thành một kho chứa:

  1. Tạo một .gitthư mục ở cấp cao nhất của kho lưu trữ của bạn.
  2. Di chuyển những thứ quản lý kho lưu trữ ( HEAD branches config description hooks info objects refsv.v.) vào những thứ .gitbạn vừa tạo.
  3. Chạy git config --local --bool core.bare falseđể chuyển đổi kho lưu trữ git cục bộ thành không trống.
  4. (thông qua bình luận của Tamás Pap ) Sau bước 3, bạn sẽ thấy rằng bạn đang ở trên chi nhánh master(hoặc bất kỳ chi nhánh chính của bạn) và tất cả các tệp của bạn đã bị xóa và việc xóa được dàn dựng. Điều đó là bình thường. Chỉ cần thanh toán theo cách thủ công masterhoặc thực hiện một git reset --hard, và bạn đã hoàn tất.
  5. (đối với vấn đề quyết tâm báo cáo của Royi ) Chỉnh sửa .git/configtập tin thêm dòng fetch = +refs/heads/*:refs/remotes/origin/*sau url = <...>trong [remote "origin"]phần. Nếu không git fetchsẽ không nhìn thấy origin/mastervà các chi nhánh của nguồn gốc khác.

Các bước này ngược lại với câu hỏi này , "git-convert normal to bare repository" - đặc biệt lưu ý câu trả lời này , trong đó nói rằng các bước ở trên (theo tôi đoán là một trong hai hướng) khác với thực hiện a git-clone. Tuy nhiên, không chắc liệu điều đó có liên quan đến bạn hay không, nhưng bạn đã đề cập git clonetrong câu hỏi.


2
Tôi đã viết tất cả, nhưng vẫn còn khi tôi đẩy các tệp, chúng không hiển thị. Nó có thể là gì (tôi cũng đã chuyển từ chốiCurrentBranch thành bỏ qua)?
Royi

Cảm ơn bạn! Một ngày nọ, tôi đến làm việc và nhận thấy repo chính của mình - nơi mà tôi đã có một số worktrees ở nơi khác - đang tự báo cáo là "trống". Tất cả các công việc khác đều ổn. Không biết làm thế nào để trở nên không cần thiết nhưng đã tìm thấy câu trả lời này và nó hoạt động rất tốt.
davidbak

17

Tôi đã có một kịch bản hơi khác:

Giải pháp:

  • sao chép một repo trần trong nội dung đó, trong một .gitdir:
    git clone --bare https://github.com/user/project .git
  • Đánh dấu nó là một repo không trần:
    git config --local --bool core.bare false
  • đặt lại chỉ mục (nếu không, nó tin rằng mọi thứ đã bị xóa, vì repo .git trần không bao gồm tệp ' index'.)
    git reset HEAD -- .
    Điều đó khôi phục .git/index.

Tôi đã chuyển đổi một cách hiệu quả một repo trần thành một repo không trần, trong khi vẫn giữ nguyên nội dung mà tôi đã có trước đó.
Tập lệnh đầy đủ mà tôi đã sử dụng trong nhiều năm bao gồm các bước:

cd /path/to/current/worktree

# That creates a .git directly at the right place
git clone --bare /url/of/repo .git

# restore the link between the local repo and its upstream remote repo
git config --local --bool core.bare false
git config --local remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git fetch origin
git branch -u origin/master master

# reset the index (not the working tree)
git reset HEAD -- .

Nhưng tôi làm trinh sát các giải pháp được chấp nhận (với hữu ích git resetbước thêm bởi ADTC ) là đơn giản hơn.


Cũng cần lưu ý rằng nếu kho lưu trữ trống được tạo trên một máy có phần cuối dòng khác nhau, bạn vẫn có thể thấy các tệp đã sửa đổi ngay cả sau khi thực hiện các bước này. Tôi tin rằng đó là điều bình thường; git đang cố gắng sửa các nguồn cấp dữ liệu. Không chắc chắn lý do tại sao.
Juno Woods

Vì vậy, về cơ bản bạn đã sao chép một repo GitHub dưới dạng trống, chuyển sang không trần, đặt tất cả tệp từ chỉ mục "không repo" và đặt lại theo cách thủ công? Nó khác gì so với việc chỉ nhân bản repo thành non-bare ngay từ đầu? Quá trình sao chép không trần sẽ kiểm tra tất cả các tệp. Và nếu bạn thực sự muốn, bạn chỉ có thể thay thế các tệp đã kiểm xuất bằng các tệp từ "không phải repo" của bạn.
ADTC

@ADTC mục tiêu là lấy một .gitthư mục con trong cây làm việc (mà bạn biết đó là repo của bạn) ban đầu được tạo từ một kho lưu trữ (không phải git). Tôi không thể kiểm tra một repo không trống, vì thư mục mà tôi đang thực hiện kiểm tra không trống. Thực hiện không để trần git clone --no-checkouttrong một thư mục con sẽ buộc tôi phải tăng .gitmột cấp. Thực hiện một bản sao trần cho phép tôi trực tiếp tạo .gitthư mục con mà tôi muốn. Bạn có thể xem kịch bản tại đây: github.com/VonC/compileEverything/blob/…
VonC

"Tôi không thể kiểm tra một repo không trống, vì thư mục mà tôi đang thực hiện kiểm tra không trống." Ý bạn là bạn có một cây làm việc không phải git có chứa các thay đổi chưa được cam kết và bạn có ý định cam kết sau khi đã chuyển đổi nó thành cây làm việc hỗ trợ Git? Vâng, tôi đoán, nó hoạt động cho một trường hợp sử dụng như vậy. Cá nhân tôi sẽ sao chép vào một thư mục trống và so sánh hai thư mục trước (sử dụng một công cụ bên ngoài). Nhưng đó chỉ là tôi.
ADTC

@ADTC Không: Tôi có không có "cây làm việc non-git chứa các thay đổi chưa được cam kết". Tôi không muốn cam kết bất cứ điều gì. Những gì tôi làm có là một cây làm việc chính xác của một repo: tất cả là mất tích là của nó .git. Tôi thực hiện được .gitthông qua một bản sao trần, tôi chuyển đổi .gitthư mục đó thành một bản sao không trần, và thực hiện một thao tác git resetđể git nhận ra rằng cây làm việc đã ở đó. Đó chính xác là những gì github.com/VonC/compileEverything/blob/… làm.
VonC

11

Để đơn giản hóa và kết hợp thông tin trong các câu trả lời:

Có ba điểm khác biệt khiến một repo trần khác với một thư mục .git bình thường:

  • core.bare được đặt thành true trong tệp cấu hình
  • tệp chỉ mục và cây làm việc không tồn tại
  • refspec mặc định cho điều khiển từ xa "origin" không được tạo

Vì vậy, bạn có thể chỉ cần di chuyển repo trần của mình thành thư mục con .git của một thư mục mới,

mkdir clone
mv bare.git clone/.git

Thay đổi core.bare:

cd clone
git config --local --bool core.bare false

Thêm một refspec gốc mặc định để tạo git fetchgit pushchọn các giá trị mặc định giống như bình thường:

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

Và tạo tệp chỉ mục và cây làm việc:

git checkout master

Tôi khuyên bạn git checkoutkhông git resetnên tạo các tệp, trong trường hợp nó vô tình bị nhập vào sai vị trí.


9

Câu hỏi của người đăng ban đầu là không có đủ không gian để thực hiện mọi việc theo cách đơn giản. Đối với những người có đủ không gian, câu trả lời đơn giản hơn nhiều:

git clone foo.git foo

Lý do tôi muốn tránh điều này là khi repo lớn, git clone đôi khi chết. Tôi muốn thực hiện một rsync của repo trần sau đó chuyển đổi nó.
Sridhar Sarnobat

@SridharSarnobat, sau đó xem xét thực hiện các tác vụ được mô tả trong câu trả lời được chấp nhận: stackoverflow.com/a/10637882/377270 - Tôi đặt câu trả lời một dòng này ở đây để những người có đủ dung lượng trống có thể thực hiện mọi việc một cách dễ dàng.
sarnold

6

Nếu bạn có ít không gian đĩa, việc mở rộng cây làm việc bằng cách chuyển đổi sang một kho lưu trữ bình thường sẽ là một vấn đề, nhưng bạn có thể duyệt nội dung của một kho lưu trữ trống mà không cần chuyển đổi nó. Sử dụng git cat-file -p <commit-sha>trên bất kỳ cam kết nào để xem cây mà nó đề cập đến. Sử dụng git cat-file -p <blob-sha>để xem nội dung của tệp được tham chiếu bởi blob. Sử dụng git show <sha>:pathtrong đó sha là một cam kết hoặc một cây để xem nội dung của đốm màu tại đường dẫn.


1
Bạn nói đúng, nhưng tôi cần duyệt nó thuận tiện hơn (trong trình quản lý tệp qua ssh). Do đó, tôi sẽ cần phải sống với dung lượng ổ đĩa tăng lên.
nyi

1
Trên thực tế, đây là một vấn đề thực sự (+1). Cây làm việc thường tiêu tốn đến một nửa không gian đĩa; một phần vì lịch sử git được nén mạnh.
jpaugh

3

cd vào repo trần và làm

  1. Hoặc:
git config core.bare false
git reset --hard
  1. hoặc là
git clone X.git X

(sẽ cung cấp cho bạn repo git thông thường có tên X)


Đây là giải pháp đơn giản nhất và tôi có thể xác nhận vào năm 2019 rằng nó hoạt động (cách tiếp cận đầu tiên).
Sridhar Sarnobat

Chỉ một lưu ý nhỏ mà tôi đã quên (áp dụng cho tất cả các câu trả lời): bạn sẽ cần chỉnh sửa tệp cấu hình khi lần đầu tiên bạn ấn để đặt url từ xa.
Sridhar Sarnobat

2

Nếu bạn không thấy phiền khi làm việc với nhiều công việc khác nhau, thì

git worktree add ../repo2
cd ..
git status # now works fine

Xin lưu ý, đây không phải là một bản sao.


Này là rất tốt, không chắc chắn tại sao điều này không phải là cao hơn trong danh sách
Nickolai

0

Đẩy để triển khai

Thay vì chuyển đổi điều khiển từ xa trần thành kho lưu trữ tiêu chuẩn, bạn có thể sử dụng tập lệnh post-nhận trong thư mục hooks để mở rộng kho lưu trữ thành thư mục triển khai.

Đây là một ví dụ điển hình về việc thiết lập Push-to-Deploy

Để dễ tham khảo, đây là ví dụ nội dung script từ liên kết trên. Nó sẽ triển khai chỉ đẩy từ nhánh "chính" đến một thư mục có tên "triển khai" ở cùng cấp với thư mục mẹ của kho lưu trữ:

#!/usr/bin/env ruby
# post-receive

# 1. Read STDIN (Format: "from_commit to_commit branch_name")
from, to, branch = ARGF.read.split " "

# 2. Only deploy if master branch was pushed
if (branch =~ /master$/) == nil
    puts "Received branch #{branch}, not deploying."
    exit
end

# 3. Copy files to deploy directory
deploy_to_dir = File.expand_path('../deploy')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
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.