Tôi sẽ sử dụng git-worktree để làm gì?


210

Tôi đọc bài đăng của Github trên git-worktree . Họ viết:

Giả sử bạn đang làm việc trong kho lưu trữ Git trên một nhánh được gọi feature, khi người dùng báo cáo lỗi khẩn cấp cao master. Trước tiên, bạn tạo một cây làm việc được liên kết với một nhánh mới hotfix, được kiểm tra liên quan đến chủ [[]] Bạn có thể sửa lỗi, đẩy hotfix và tạo yêu cầu kéo.

Khi tôi đang làm việc trên một nhánh gọi là tính năng và một số lỗi khẩn cấp cao trong chủ được báo cáo, tôi thường loại bỏ bất cứ thứ gì tôi đang làm và tạo một nhánh mới. Khi tôi hoàn thành, tôi có thể tiếp tục làm việc. Đây là một mô hình rất đơn giản, tôi đã làm việc như thế trong nhiều năm.

Mặt khác, sử dụng git-worktree có những hạn chế riêng:

Ví dụ, không được phép kiểm tra cùng một nhánh trong hai cây làm việc được liên kết cùng một lúc, bởi vì điều đó sẽ cho phép các thay đổi được cam kết trong một cây làm việc không đồng bộ hóa.

Tại sao tôi chọn một quy trình công việc phức tạp hơn cho một vấn đề đã được giải quyết?

Có bất cứ điều gì về git-worktreeđiều đó không thể được thực hiện trước đó và điều đó biện minh cho tính năng hoàn toàn mới, phức tạp này?


12
Một điều bạn không thể bỏ qua là các đường dẫn không được trộn lẫn, sau khi hợp nhất hoặc nổi loạn với các xung đột.
chirlu

11
Nếu bạn làm việc với một ngôn ngữ được biên dịch, stashing có nghĩa là bạn sẽ phải biên dịch lại mọi thứ khi bạn chưa khai thác.
mb14

Chúng tôi có một số sản phẩm khác nhau dựa trên cùng một mã nguồn (300 MB) và tôi dự định kết hợp tất cả chúng thành một repo lớn và sử dụng worktree để giữ mỗi sản phẩm được kiểm tra trong một thư mục khác nhau, thay vì có một đống lớn bản sao không đồng bộ
endolith

Câu trả lời:


195

Đối với tôi, git worktree là sự cải tiến lớn nhất trong một thời gian dài. Tôi đang làm việc trong lĩnh vực phát triển phần mềm doanh nghiệp. Ở đó, điều rất phổ biến là bạn phải duy trì các phiên bản cũ như những gì bạn đã phát hành 3 năm trước. Tất nhiên bạn có một chi nhánh cho mỗi phiên bản để bạn có thể dễ dàng chuyển sang nó và sửa lỗi. Tuy nhiên, chuyển đổi là tốn kém, vì trong khi đó, bạn hoàn toàn cấu trúc lại kho lưu trữ và có thể xây dựng hệ thống. Nếu bạn chuyển đổi, IDE của bạn sẽ phát điên khi cố gắng điều chỉnh các cài đặt dự án.

Với worktree, bạn có thể tránh cấu hình lại liên tục đó. Kiểm tra các nhánh cũ trong các thư mục riêng biệt bằng cách sử dụng worktree. Đối với mỗi chi nhánh, bạn có một dự án IDE độc lập.

Tất nhiên điều này có thể đã được thực hiện trong quá khứ bằng cách nhân bản repo nhiều lần và đây là cách tiếp cận của tôi cho đến nay. Tuy nhiên, điều đó cũng có nghĩa là lãng phí không gian cứng và tệ hơn là cần tìm nạp các thay đổi tương tự từ repo nhiều lần.


4
Bạn đã không phải tìm nạp các thay đổi tương tự từ repo nhiều lần. Bạn có thể đã sao chép đơn giản thư mục .git của bản sao đầu tiên.
misiu_mp

1
@ jdk1.0 xin lỗi vì sự nhầm lẫn, bình luận được gửi trực tiếp tại misiu_mp
mxttie

2
Là một người đã sử dụng 2-3 repos sao chép cao để tôi có thể xây dựng một nhánh tính năng trong khi phát triển trên một nhánh khác, tôi đã từng repo cục bộ như là điều khiển từ xa của những người khác và tôi hoàn toàn đồng ý với các đặc điểm của nhược điểm của Sebi (rất nhiều tìm nạp và đẩy! ) Ngoài ra, một khi tôi chuyển sang làm việc, tôi tập hợp rằng tôi sẽ không còn phải lo lắng về việc chuyển hướng các nhánh cùng tên cục bộ (điều này xảy ra khoảng 6-10 tháng một lần khi tôi bị gián đoạn nhiều lần trong một khoảng thời gian và kết thúc làm việc cùng một nhánh tính năng trong số nhiều repos, nhưng quên đồng bộ hóa chúng sao lưu ...)
hiền nhân

3
@iheanyi - (1). Sẽ nhanh hơn nếu IDE duy trì các tệp dữ liệu ngoài (như cơ sở dữ liệu lập chỉ mục) được liên kết với một thư mục nhất định. Nếu bạn xóa nội dung trong cùng một thư mục, điều đó thường sẽ làm mất hiệu lực bất kỳ bộ đệm dữ liệu IDE nào và nó sẽ phải lập chỉ mục lại.
Steve Hollasch

5
@iheanyi - (2) Theo thời gian, lịch sử của mọi thứ sẽ phát triển lớn hơn nhiều so với các tệp cây làm việc tại bất kỳ điểm nào. Lịch sử của mọi thứ == .gitthư mục. Với nhiều bản sao cục bộ từ thượng nguồn, bạn có nhiều bản sao cục bộ của cùng một cơ sở dữ liệu, vì mỗi bản sao có .gitcơ sở dữ liệu riêng . Với nhiều cây làm việc cục bộ, mỗi cây sử dụng cùng một .gitcơ sở dữ liệu. Có, nếu bạn có bản sao cục bộ của nơi làm việc tại địa phương, Git sẽ liên kết cứng rất nhiều nội dung .git, nhưng không có trên Windows.
Steve Hollasch

70

Tôi có thể thấy một số sử dụng cho việc này.

Nếu bạn có một bộ kiểm tra chạy trong một thời gian dài, hãy tưởng tượng hàng giờ và bạn khởi động nó một cách hiệu quả để chặn bản sao làm việc đó cho đến khi các bài kiểm tra được hoàn thành. Chuyển đổi các nhánh trong các thử nghiệm đó sẽ phá vỡ chúng theo những cách khó hiểu.

Vì vậy, với git-worktreetôi có thể có một ý tưởng thứ hai được đưa ra cho một chi nhánh khác đang làm việc ở đó.

Ngoài ra, khi tôi chuyển sang một số chi nhánh khác để thực hiện một số điều tra nhanh, IDE của tôi nghĩ rằng rất nhiều tệp đột nhiên thay đổi và sẽ lập chỉ mục tất cả những thay đổi đó, chỉ cần phải lập chỉ mục lại chúng khi tôi chuyển trở lại.

Trường hợp sử dụng thứ ba sẽ là so sánh tệp bằng các công cụ khác git-diff, như bình thường diff, giữa hai thư mục thay vì nếu hai nhánh.


6
Sẽ không git clonelàm việc tốt cho tất cả những điều này?
jthill

12
Nó sẽ nhưng nhân bản một kho lưu trữ lớn từ xa có thể mất nhiều thời gian. Tôi đang làm việc với một kho lưu trữ mất vài phút để sao chép. Tôi đoán rằng bạn có thể làm điều đó với git clone --reference. Ngoài ra, việc quản lý tất cả các chi nhánh khác sẽ được thực hiện chỉ một lần thay vì một lần cho mỗi thư mục làm việc.
Andreas Wederbrand

6
Đừng nhân bản từ xa, nhân bản từ địa phương của bạn. Tôi không hiểu vấn đề quản lý chi nhánh, bạn có thể làm rõ?
jthill

14
Tôi đã cố gắng sử dụng bản sao, và thực sự có một vấn đề quản lý. Thay vì một nhánh duy nhất, tôi có một nhóm nhân bản, mà tôi không thể thấy tất cả cùng nhau trong một UI. Nếu tôi cần chọn một số thay đổi, tôi phải tìm nạp hoặc đẩy chúng xung quanh. Nó thêm các bước bổ sung cho tất cả các hành động. Mọi thứ đều có thể làm được, nhưng luôn có một số ma sát.
max630

2
Và khi nói đến việc thiết lập một bản sao lưu, kho lưu trữ đơn lẻ dễ dàng hơn nhiều.
max630

64

Một cách sử dụng rõ ràng là đồng thời so sánh hành vi (không phải nguồn) của các phiên bản khác nhau - ví dụ các phiên bản khác nhau của một trang web hoặc chỉ một trang web.

Tôi đã thử điều này tại địa phương.

  • tạo một thư mục page1.

  • bên trong tạo thư mục srcgit initnó.

  • trong srctạo page1.htmlvới một ít nội dung và cam kết nó.

  • $ git branch ver0

  • $ git worktree add ../V0 ver0

  • trong srctổng thể thêm văn bản vào page1.htmlvà cam kết nó.

  • $ git branch sty1

  • chỉnh sửa page1.htmltrong sty1nhánh (thêm một số kiểu CSS đặc biệt) và thêm cam kết.

  • $ git worktree add ../S1 sty1

Bây giờ bạn có thể sử dụng trình duyệt web để mở và xem 3 phiên bản này cùng một lúc:

  • ..\page1\src\page1.html // bất cứ điều gì git có như hiện tại

  • ..\page1\V0\page1.html // phiên bản ban đầu

  • ..\page1\S1\page1.html // phiên bản thử nghiệm


2
Tôi không thấy cách này giải thích lợi ích của việc sử dụng worktree cho mục đích này trên bản sao.
iheanyi

@iheanyi Bạn có thể nói như vậy về branch; câu trả lời cũng vậy: đó là trọng lượng nhẹ hơn và được chế tạo cho công việc.
OJFord

1
@OJFord đó là một điểm. Câu trả lời này không giải thích cho tôi những gì worktree làm điều đó khác nhau. Rõ ràng đó không phải là bí danh cho chi nhánh hoặc bản sao nhưng hiệu ứng tôi thấy ở đây dường như là giống nhau. Tôi không thấy làm thế nào đây là bất kỳ trọng lượng nhẹ hơn so với chỉ sử dụng chi nhánh hoặc bản sao.
iheanyi

@iheanyi Khác với việc sử dụng chi nhánh - bạn không thể sử dụng các chi nhánh một mình để có được nhiều trạng thái của bàn làm việc cùng một lúc - và trọng lượng nhẹ hơn so với bản sao thứ hai (.., nth). Điều tôi muốn nói là bạn cũng có thể nói về chi nhánh 'tại sao không chỉ sao chép và thực hiện các thay đổi của bạn', nhưng nhiều chi nhánh trong một repo duy nhất có trọng lượng nhẹ hơn và cách quản lý dễ dàng hơn để có được hành vi đó.
OJFord

@OJFord Tôi không nghĩ rằng điều này giải quyết sự nhầm lẫn của tôi với worktree. Để tôi nói theo cách này, cho dù bạn sử dụng chi nhánh hay nhân bản hay thứ gì khác, mục tiêu cuối cùng của quy trình được mô tả ở đây là so sánh ba phiên bản khác nhau của một cái gì đó cùng một lúc. Dựa trên những gì trong câu trả lời, tôi không hiểu tại sao tôi lại sử dụng worktree thay vì một số thay thế. Câu trả lời không giải thích những gì worktree đang làm mà các lựa chọn thay thế không. Bạn đưa ra tuyên bố về một cái gì đó nhẹ (hoặc trọng lượng nhẹ hơn) nhưng tôi không thấy cách thức làm việc làm cho các chi nhánh bớt "trọng lượng".
iheanyi

29
  1. Có nhiều lý do chính đáng tại sao bạn có thể muốn / cần nhiều bàn làm việc trong hệ thống tệp cùng một lúc.

    • thao tác với các tệp đã kiểm tra trong khi cần thực hiện thay đổi ở một nơi khác (ví dụ: biên dịch / kiểm tra)

    • khuếch tán các tập tin thông qua các công cụ khác thường

    • trong các xung đột hợp nhất, tôi thường muốn điều hướng qua mã nguồn vì nó ở phía nguồn trong khi giải quyết xung đột trong các tệp.

    • Nếu bạn cần chuyển đổi qua lại nhiều, sẽ lãng phí thời gian kiểm tra và kiểm tra lại rằng bạn không cần phải làm gì với nhiều công việc.

    • chi phí tinh thần của bối cảnh tinh thần chuyển đổi giữa các chi nhánh thông qua git stashing là không thực sự có thể đo lường được. Một số người thấy rằng có chi phí tinh thần cho việc bỏ rác không có ở đó chỉ bằng cách mở các tệp từ một thư mục khác.

  2. Một số người hỏi "tại sao không làm nhiều bản sao địa phương". Đúng là với cờ "--local", bạn không phải lo lắng về việc sử dụng thêm dung lượng đĩa. Điều này (hoặc ý tưởng tương tự) là những gì tôi đã làm cho đến thời điểm này. Các lợi ích chức năng đối với các bàn làm việc được liên kết so với các bản sao cục bộ là:

    1. Với các bản sao cục bộ, các bảng công việc bổ sung của bạn (nằm trong các bản sao cục bộ) đơn giản là không có quyền truy cập vào các nhánh gốc hoặc ngược dòng. 'Nguồn gốc' trong bản sao sẽ không giống với 'nguồn gốc' trong bản sao đầu tiên.

      • Chạy git log @{u}..hoặc git diff origin/feature/other-featurecó thể rất hữu ích và những điều này là không thể hoặc khó khăn hơn. Những ý tưởng này về mặt kỹ thuật là có thể với các bản sao cục bộ thông qua một loại các từ khác, nhưng mọi cách giải quyết bạn có thể làm được thực hiện tốt hơn và / hoặc đơn giản hơn thông qua các bảng tính được liên kết.
    2. Bạn có thể chia sẻ ref giữa các worktrees. Nếu bạn muốn so sánh hoặc mượn các thay đổi từ một chi nhánh địa phương khác, bây giờ bạn có thể.


11
Ngoài ra, bạn có thể liệt kê tất cả các bàn làm việc với một lệnh duy nhất, với bản sao bạn cần tự theo dõi chúng.
Ian Ringrose

hmm Kể từ git 2.7.0 dường như là trường hợp. Rất vui được biết.
Alexander Bird

9

tl; dr: Bất cứ lúc nào bạn muốn có hai cây làm việc được kiểm tra cùng một lúc vì bất kỳ lý do gì, git-worktree là một cách nhanh chóng và tiết kiệm không gian để thực hiện.

Nếu bạn tạo một worktree khác, hầu hết các phần của repo (nghĩa là .git) sẽ được chia sẻ, nghĩa là nếu bạn tạo một nhánh hoặc lấy dữ liệu trong khi bạn ở trong một cây làm việc, nó cũng sẽ có thể truy cập được từ bất kỳ cây công việc nào khác mà bạn có. Giả sử bạn muốn chạy bộ thử nghiệm của mình trên nhánh foo mà không cần phải đẩy nó ra một nơi nào đó để sao chép nó và bạn muốn tránh những rắc rối khi sao chép repo cục bộ của mình, sử dụng git-worktreelà một cách hay để tạo ra một kiểm tra mới của một số trạng thái trong một nơi riêng biệt, tạm thời hoặc vĩnh viễn. Giống như với một bản sao, tất cả những gì bạn cần làm khi hoàn thành nó là xóa nó và tham chiếu đến nó sẽ là rác được thu thập sau một thời gian.


2
Tài liệu nói rằng bạn không thể có cùng một chi nhánh trong cả hai bản sao làm việc, đây là một hạn chế nghiêm trọng. Với Mercurial, nó chỉ hoạt động với các vấn đề nhỏ.
hypersw

Chắc chắn bạn có thể. Trang đàn ông nói như thế nào; tìm kiếm --force. Nhưng thật bất tiện nếu bạn cập nhật chi nhánh ở một nơi và mong đợi làm việc ở chi nhánh khác, vì worktree không được cập nhật.
jsageryd

Đúng, các nhánh trong Mercurial là một khái niệm minh bạch hơn trong khía cạnh này. Làm thế nào để các chi nhánh từ một worktree xuất hiện trong khác? Cùng một cách với nhiều đường lên? Các thử nghiệm đầu tiên của tôi với bàn làm việc, với việc chạy tìm nạp cả hai, kết thúc với hai con trỏ (!) Khác nhau (!) Được đặt tên origin/master.
hypersw

Một worktree là (như tên ngụ ý) chỉ là một worktree, với một số tính năng bổ sung; kho lưu trữ được chia sẻ giữa tất cả các bàn làm việc. Sự khác biệt duy nhất giữa hai worktrees là nhánh thanh toán có thể (và đối với quy trình công việc lành mạnh, là) khác nhau. Có thể cam kết trong một worktree riêng, vì vậy nó cũng có chỉ mục riêng (còn gọi là khu vực tổ chức) để thực hiện công việc đó. Các .gittập tin trong worktree riêng là một tập tin văn bản có chứa đường dẫn đến cấu hình của nó, mà nằm trong kho lưu trữ ban đầu.
jsageryd

2
@WilsonF: git checkout --ignore-other-worktrees <branch> git-scm.com/docs/git-checkout/ từ
jsageryd

7

Ban đầu tôi vấp phải câu hỏi này sau khi tự hỏi những bàn làm việc ưa thích này có thể được sử dụng để làm gì. Kể từ đó, tôi đã tích hợp chúng vào quy trình làm việc của mình và bất chấp sự hoài nghi ban đầu của tôi, tôi đã đến để thấy chúng khá hữu ích.

Tôi làm việc trên một cơ sở mã khá lớn, mất khá nhiều thời gian để biên dịch. Tôi thường có nhánh phát triển hiện tại trên máy của mình cùng với nhánh tính năng tôi hiện đang làm việc cộng với nhánh chính, đại diện cho trạng thái hiện tại của hệ thống trực tiếp.

Một trong những lợi ích lớn nhất đối với tôi rõ ràng là tôi không phải biên dịch lại toàn bộ mọi thứ mỗi khi tôi chuyển đổi chi nhánh (nghĩa là, bàn làm việc). Một hiệu ứng phụ tuyệt vời là tôi có thể đi đến worktree phát triển, làm công cụ ở đó, thay đổi thư mục thành worktree cho nhánh tính năng hiện tại của tôi và sau đó khởi động lại mà không cần phải kéo trước.


4

Tôi có một điều khá bất thường: Tôi đang phát triển Windows và Linux trên cùng một máy . Tôi có một VirtualBox chạy Linux bên trong hộp Windows của mình. VirtualBox gắn kết một số thư mục Windows và sử dụng chúng trực tiếp bên trong máy Linux. Điều này cho phép tôi sử dụng Windows để quản lý các tệp nhưng xây dựng trong Linux. Đây là một dự án đa nền tảng, vì vậy nó xây dựng trên cả Windows và Linux từ cùng một cấu trúc thư mục.

Vấn đề là các hệ thống xây dựng Linux và Windows đâm sầm vào nhau khi được sử dụng trong cùng một thư mục; có một số bước xây dựng phức tạp để tải xuống thư viện, v.v., sử dụng cùng tên thư mục. Phiên bản Windows của hệ thống xây dựng tải xuống các thư viện dành riêng cho Windows và phiên bản Linux của hệ thống xây dựng tải xuống các thư viện dành riêng cho Linux.

Trong một thế giới lý tưởng, hệ thống xây dựng sẽ được sửa đổi để Windows & Linux có thể cùng tồn tại trong thư mục, nhưng hiện tại, vấn đề đang được giải quyết với các bảng tính. Thư mục "Linux" có thể tạo các tạo phẩm xây dựng dành riêng cho Linux và thư mục "Windows" có thể tạo các tạo phẩm xây dựng dành riêng cho Windows. Mặc dù đây không phải là một giải pháp lý tưởng, nhưng nó tạo ra một điểm dừng tốt đẹp trong khi chờ đợi các lỗi hệ thống xây dựng được giải quyết.

Phải thừa nhận rằng, worktree không được thiết kế cho việc này; Tôi phải giữ phiên bản Windows và phiên bản Linux trên các nhánh riêng biệt, mặc dù tôi thực sự thích chúng ở cùng một nhánh. Tuy nhiên, đó là công việc, và là một trường hợp hơi độc đáo của công việc tiết kiệm trong ngày.


+1 Đây có vẻ như là một cách giải quyết rất hiệu quả đối với Make không thực hiện các thư mục đầu ra xây dựng theo cấu hình nguyên bản. Tôi có một thiết lập VMware Workstation tương tự với các khách Ubuntu và macOS.
Tanzania87

1

Trong dự án mới đối với tôi, tôi đã tạo ra một tính năng. Nhưng một số thông số kỹ thuật thất bại. Để so sánh kết quả với mastertôi đã tạo ra một work-treerepo. Tôi so sánh kết quả từng bước trong mã chạy, cho đến khi hiểu những gì đã sai.


Làm thế nào để một worktree làm điều này dễ dàng hơn so với một bản sao, mặc dù? Câu hỏi không phải là yêu cầu cá nhân, mà là sự khác biệt cụ thể.
IInspectable 20/11/18

1

Tôi đang sử dụng git worktree để phát triển máy học.

Tôi có một mã chức năng chính và sau đó tôi muốn phân chia các nhánh của các thử nghiệm khác nhau (các thuật toán khác nhau và các siêu đường kính khác nhau). git worktreecho phép tôi tích hợp dvc cùng với các phiên bản mã khác nhau của tôi chuyên cho các thuật toán khác nhau. Sau khi chạy tất cả các công việc đào tạo, tôi đánh giá các số liệu cuối cùng và hợp nhất để làm chủ chi nhánh / mô hình tốt nhất.

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.