Làm cách nào để tạo một nhánh mới (và trống!)


135

Tôi muốn xác định một nhánh "gốc" mới trong kho git này. Theo nhánh "gốc", ý tôi là một nhánh hoàn toàn độc lập với tất cả các nhánh khác trong kho 1 .

Thật không may, ngay cả các cam kết (hãy gọi nó A) ở chính gốc cây cam kết của repo chứa rất nhiều tệp (đây là một kho lưu trữ được khởi tạo trong một dự án đã khá hoàn thiện).

Điều này có nghĩa là ngay cả khi tôi đã cho Alà chi nhánh mới <start-point>, chi nhánh mới này sẽ không bắt đầu từ "bảng xếp hạng sạch", mà thay vào đó, nó sẽ chứa tất cả các tệp đã được cam kết A.

Có cách nào để tôi có thể tạo một nhánh hoàn toàn trống trong kho lưu trữ này, <start-point>càng gần Acàng tốt không?


1 BTW, điều này không tương đương với việc tạo một repo mới. Repos riêng sẽ ít thuận tiện hơn vì nhiều lý do.


EDIT : OK, đây là những gì tôi đã làm, dựa trên câu trả lời của vcsjones :

# save rev of the current earliest commit
OLDBASE=$(git rev-list --max-parents=0 HEAD)

# create a new orphan branch and switch to it
git checkout --orphan newbranch
# make sure it's empty
git rm -rf .

# create a new empty commit in the new branch, and
# save its rev in NEWBASE
git commit --allow-empty -m 'base commit (empty)'
NEWBASE=$(git rev-list HEAD)

# specify $NEWBASE as the new parent for $OLDBASE, and
# run filter-branch on the original branch
echo "$OLDBASE $NEWBASE" > .git/info/grafts
git checkout master
git filter-branch

# NOTE: this assumes that the original repo had only one
# branch; if not, a git-filter-branch -f <branch> command
# need to be run for each additional branch.

rm .git/info/grafts

Mặc dù thủ tục này có một chút liên quan, kết quả cuối cùng là một cam kết cơ sở trống có thể đóng vai trò <start-point>cho bất kỳ "nhánh sạch" mới nào; tất cả những gì tôi cần làm sau đó là

git checkout -b cleanslate $(git rev-list --max-parents=0 HEAD)

Trong tương lai tôi sẽ luôn tạo các kho lưu trữ mới như thế này:

git init
git commit --allow-empty -m 'base commit (empty)'

... để cam kết đầu tiên trống và luôn có sẵn để bắt đầu một chi nhánh độc lập mới. (Điều này sẽ là, tôi biết, một cơ sở rất hiếm khi cần, nhưng khá dễ dàng để làm cho nó có sẵn.)



1
@Anonymousoose: Chỉ dành cho hồ sơ (chứ không phải tranh luận): Tôi không đồng ý với ý kiến ​​của bạn.
kjo

1
Dường như có một giải pháp đơn giản hơn nhiều dựa trên git rebase --onto, hãy xem stackoverflow.com/questions/645450/iêu
Stéphane Gourichon

Câu trả lời:


222

Sử dụng --orphankhi tạo chi nhánh:

git checkout --orphan YourBranchName

Điều này sẽ tạo ra một nhánh mới với số lần cam kết bằng 0, tuy nhiên tất cả các tệp của bạn sẽ được tổ chức. Tại thời điểm đó bạn chỉ có thể loại bỏ chúng.
("xóa chúng": A git reset --hardsẽ làm trống chỉ mục, để lại cho bạn một cây làm việc trống)

Hãy xem trang người đàn ông để kiểm tra để biết thêm thông tin về - định dạng.


Điều này về cơ bản tạo ra một bảng trống? Như trong, từ đầu? Hoặc nó giữ tất cả các thay đổi trước đó của bạn, nhưng chỉ là không có trong lịch sử git?
Con Antonakos

4
@ConAntonakos Điều này tạo ra một chi nhánh mới mà không có cha mẹ. Các chi nhánh khác không bị ảnh hưởng, tất cả các thay đổi của họ được giữ.
fuz

11

Để thêm vào câu trả lời được chấp nhận - cách tốt nhất để trở lại trạng thái sạch là tạo một cam kết trống ban đầu để bạn có thể dễ dàng bắt đầu lại trong khi thiết lập các nhánh của mình cho hậu thế. Ngoài ra, vì bạn muốn có một trạng thái sạch, có thể bạn đã cam kết các tệp mà bạn không nên, vì vậy bạn phải xóa chúng khỏi chỉ mục. Với những người trong tâm trí bạn nên:

$ git checkout --orphan dev2
Switched to a new branch 'dev2'
$ git reset # unstage all the files, you probably don't want to commit all of them
$ git commit --allow-empty -m 'Initial empty commit'
[dev2 (root-commit) a515c28] Initial empty commit

1
Tôi tin rằng điều này là không cần thiết kể từ năm 2012 bởi vì bạn có thể rebase lên root .
Timmmm


1

Có cách nào để tôi có thể tạo một nhánh hoàn toàn trống trong kho lưu trữ này.

Lệnh thực tế để sử dụng (với Git 2.28+) là:

git switch --discard-changes --orphan newBranch
# or
git switch -f --orphan newBranch

git switchcó sẵn từ Git 2.23 (tháng 8 năm 2019) và thay thế lệnh khó hiểu cũgit checkout .

Nhưng tôi muốn giới thiệu Git 2.28 (quý 3 năm 2020), vì git switch --discard-changes --orphanđã được tối ưu hóa trong phiên bản đó.

Xem cam kết 8d3e33d , cam kết 8186128 (ngày 21 tháng 5 năm 2020) bởi brian m. carlson ( bk2204) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết44 , ngày 09 tháng 6 năm 2020)

builtin/checkout: đơn giản hóa việc khởi tạo siêu dữ liệu

Đã ký tắt: brian m. carlson
Được đánh giá bởi: Derrick Stolee

Khi chúng ta gọi là init_checkout_metadatatrong reset_tree,chúng ta muốn vượt qua các đối tượng ID của cam kết trong câu hỏi để nó có thể được chuyển tới các bộ lọc, hoặc nếu không có cam kết, cây.

Chúng tôi đã dự đoán trường hợp sau này, có thể xảy ra ở nơi khác trong mã thanh toán, nhưng nó không thể xảy ra ở đây.

Trường hợp duy nhất mà chúng ta không có đối tượng cam kết là khi gọi git switchvới --orphan.

Hơn nữa, chúng ta chỉ có thể nhấn đường dẫn mã này mà không có đối tượng cam kết bổ sung với --forcehoặc --discard-changes.

Trong trường hợp như vậy, không có điểm nào khởi tạo siêu dữ liệu thanh toán bằng một cam kết hoặc cây vì

  • (a) không có cam kết, chỉ có cây trống và
  • (b) chúng tôi sẽ không bao giờ sử dụng dữ liệu, vì sẽ không có tệp nào bị nhoè khi kiểm tra một nhánh không có tệp.

Vượt qua ID đối tượng tất cả số không trong trường hợp này, vì chúng ta chỉ cần một số giá trị là con trỏ hợp lệ.

Kiểm tra:

git switch master
echo foo >foo.txt
git switch --discard-changes --orphan new-orphan2
git ls-files >tracked-files
# test_must_be_empty tracked-files
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.