2013-06-21 41 views
13

Tôi có một số dự án phụ thuộc vào cùng một thư viện, mà tôi muốn duy trì một kho lưu trữ git riêng biệt để được quản lý với git-subtree trong mỗi dự án. Vì vậy, ví dụ, trong mỗi dự án tôi có thể làm:xung đột git-subtree khi kéo từ repo trung tâm

project1$ git subtree add --prefix=lib1 /path/to/lib1.git master 
project2$ git subtree add --prefix=lib1 /path/to/lib1.git master 

Bây giờ trong quá trình làm việc trên project1, tôi thực hiện một số thay đổi để lib1, nói lib1/file1.c, và đẩy lùi này để repo Trung ương:

project1$ git add lib1/file1.c 
project1$ git commit -m "updates to lib1" 
project1$ git subtree push --prefix=lib1 /path/to/lib1.git master 

Cho đến nay, rất tốt. Nhưng bây giờ tôi muốn cập nhật bản sao lib1 của project2. Vì vậy, tôi thử:

project2$ git subtree pull --prefix=lib1 /path/to/lib1.git master 
Auto-merging lib1/file1.c 
CONFLICT (content): Merge conflict in lib1/file1.c 
Automatic merge failed; fix conflicts and then commit the result. 

Điều gì đang xảy ra? Tôi biết chắc chắn rằng không có thay đổi nào được thực hiện đối với bất kỳ tệp lib1 nào trong project2, vậy tại sao lại có xung đột ở đây?

Xung đột là một nửa trống, giống như những báo cáo được báo cáo trong this question. Tất cả mọi thứ đang được kéo/đẩy trong một hệ thống duy nhất (OS X), vì vậy tôi biết không có vấn đề với kết thúc dòng như đề xuất ở đó.

Chắc chắn đây là trường hợp sử dụng phổ biến cho git-subtree và có một câu trả lời đơn giản mà tôi không thể thấy. Hãy giúp tôi!

EDIT: Tôi tìm thấy một workaround không thỏa mãn: ngay sau khi đẩy thay đổi đối với cây con, tôi cần phải tái chạy subtree kéo:

project1$ git subtree push --prefix=lib1 /path/to/lib1.git master 
project1$ git subtree pull --prefix=lib1 /path/to/lib1.git master 

Mặc dù không có thay đổi, nó sẽ tìm thấy một cái gì đó, và thực hiện cam kết hợp nhất. Sau đó, sau khi thực hiện một số thay đổi ở nơi khác, cuộc xung đột sẽ không xảy ra lần thứ hai tôi rút khỏi repo trung tâm. Nhưng nếu tôi quên chạy kéo ngay lập tức sau khi đẩy, kéo tiếp theo sẽ nhận được cuộc xung đột này.

Vì vậy, bây giờ câu hỏi của tôi là, tại sao tính năng này hoạt động? Có một lỗi trong cách git-subtree bài hát đẩy, hoặc tôi thiếu một cái gì đó?

+0

Tuy nhiên, tôi có thể xem xét một khối hexdump của các dòng bị ảnh hưởng. CR có thể đã lén lút bằng cách nào đó, ví dụ: bằng cách dán văn bản từ một số nguồn khác. – chirlu

+0

Tôi đã kiểm tra hexdump cho tệp ở mỗi bước, không có CR's (0d) ở bất kỳ đâu, chỉ LF (0a). Vì vậy, đây không phải là vấn đề, mặc dù nó là tốt để kiểm tra. – user2509951

+0

Nó có thể, tất nhiên, là một số loại lỗi. Git subtree là tương đối mới, sau khi tất cả. Nếu bạn có thể đưa ra một trường hợp thử nghiệm có thể tái sản xuất, bạn có thể viết thư cho danh sách gửi thư git. – chirlu

Trả lời

2

Vâng, có vẻ như đó là lỗi trong git-subtree. Tôi đã đánh giá nó cho các nhu cầu của tôi và đã từ bỏ. Về cơ bản, git-subtree push thay đổi thông điệp cam kết và do đó, SHA1 cam kết thay đổi. Bạn phải kéo để hợp nhất các cam kết bổ sung để giới thiệu chính xác các thay đổi tương tự nhưng chỉ có các hàm băm SHA1 khác nhau do các thư cam kết bị thay đổi. GIT xử lý hợp nhất kép (sáp nhập các thay đổi giống nhau một lần nữa) một cách chính xác, vì vậy nó âm thầm ghi chú hợp nhất.

Ai đó phải sửa lỗi đó!

+2

Điều đó giải thích tại sao push-then-pull hoạt động như nó, cảm ơn. Đó là bực bội mà subtree không thể xử lý như một kịch bản đơn giản tự động. Có cách nào khác để thực hiện cú đẩy có thể tránh thay đổi SHA1 hay chúng ta quay lại sử dụng mô-đun con? – user2509951

+0

Có vẻ như nó chưa được sửa. Tôi đã có cùng một vấn đề ngay bây giờ. – zhekaus

5

Tôi thực sự đã tìm ra cách thích hợp để thực hiện việc này thông qua một số thử nghiệm và lỗi.

Sau lệnh này:

project1$ git subtree push --prefix=lib1 /path/to/lib1.git master 

thực thi một lệnh lấy:

project2$ git fetch /path/to/lib1.git master 

và sau đó làm kéo của bạn:

project2$ git subtree pull --prefix=lib1 /path/to/lib1.git master 
+1

Đây phải là câu trả lời được chấp nhận. Chính xác những gì tôi cần. – hidefromkgb

4

Có tiếc là không có cách tốt để chia cam kết ra của cây mà không đưa ra các cam kết mới được chia tách hoàn toàn khác nhau. Điều này là bởi vì họ là, sau khi tất cả, cam kết khác nhau: họ không chứa các phần không có trong cây con.Điều đó có nghĩa là khi bạn kéo chúng trở lại, git sẽ xem chúng như là các cam kết hoàn toàn mới và tạo ra một xung đột.

Có hai việc bạn có thể làm. Một trong những câu trả lời khác đề nghị làm một git subtree kéo ngay sau khi bạn đẩy. Điều này sẽ làm việc, nhưng bạn kết thúc với hai bản sao của mỗi cam kết vì thực sự có hai bộ thay đổi kỹ thuật: những cái đầu dòng (được tạo tự động bởi git-subtree push/split) và những cái trong dự án kết hợp của bạn, và bạn hợp nhất chúng lại với nhau. Một lối tắt cho phương thức này là tùy chọn --rejoin để phân chia/đẩy, điều này bổ sung thêm cam kết hợp nhất ngay lập tức.

Tùy chọn thứ hai là sử dụng --squash. Điều này cũng tạo ra các cam kết hợp nhất mới, nhưng kể từ khi bạn hợp nhất tất cả các thay đổi từ kho lưu trữ phía trên dưới dạng một cam kết thay vì một thay vì một cam kết ban đầu, nó gây ra ít lộn xộn hơn trong lịch sử của bạn. Hầu hết mọi người dường như thích nó hơn với --squash.

1

Bên trong dự án chính của bạn, hãy cố gắng kéo và đẩy với các lệnh bí luôn:

bước 1: cây con kéo với một bí

git subtree pull --prefix=mainProjectFolder/subtreeFolder http://bitbucket.org/repo.git master --squash 

bước 2: cây con đẩy với một bí

git subtree push --prefix=mainProjectFolder/subtreeFolder http://bitbucket.org/repo.git master --squash 

cờ bíp sẽ tránh tạo ID SHA1 mới cho cùng một cam kết trong các kho lưu trữ khác nhau.

Giải thích: Để khắc phục vấn đề này, bạn có thể sử dụng cờ bíp trong khi đẩy và kéo cây con của bạn. Vấn đề được mô tả bởi @Borg về SHA1 cam kết của id là chính xác, nhưng subtree đã không thực sự được xây dựng cho việc này. Bạn nên tránh giữ ID cam kết 'của kho lưu trữ thư viện con (subtree (library) trong cả dự án cha và dự án subtree. Và nếu ở tất cả các bạn đẩy các thay đổi từ kho lưu trữ gốc vào kho lưu trữ subtree, hãy thực hiện theo tuyên bố này từ tài liệu (dòng 58): That is, if you make a change that affects both the library and the main application, commit it in two pieces.

Giải thích điều này khi không sử dụng subtrees. Kéo thẳng đến phút 11:00 đến tìm của cây con mà không phải là giải pháp đúng cho bạn nếu:

bạn có cập nhật liên tục để các kho lưu trữ,

hoặc, nếu bạn có nhiều phụ thuộc,

hoặc, nếu tất cả mọi người trong nhóm phải học subtrees.

Các vấn đề liên quan