2009-08-17 34 views
14

Có một vị trí đặc biệt trong địa ngục cho những người mã hóa đường dẫn tuyệt đối và thông tin đăng nhập cơ sở dữ liệu vào nhiều vị trí ngẫu nhiên trong các ứng dụng web. Đáng buồn thay, trước khi họ đi đến địa ngục, họ đang tàn phá trái đất. Và chúng ta phải đối phó với mã của họ.git: làm cách nào để hợp nhất giữa các nhánh trong khi vẫn giữ một số thay đổi dành riêng cho một chi nhánh?

Tôi phải thực hiện một vài thay đổi nhỏ đối với một trong các ứng dụng web như vậy. Tôi tạo một chi nhánh mới features và thực hiện tìm kiếm toàn cầu & thay thế để cập nhật đường dẫn và thông tin đăng nhập vào môi trường cục bộ của tôi. Tôi cam kết điều đó. Tôi cũng gắn thẻ tên này là local.

Tôi vui vẻ nhảy vào sự huyên náo, và sau hàng trăm bản vá lỗi, tôi muốn hợp nhất các thay đổi features vào chi nhánh master, nhưng tôi không muốn hợp nhất local.

trở đi, tôi sẽ được sáp nhập lại giữa masterfeatures, và tôi muốn local để duy trì đưa vào features, và không bao giờ xuất hiện trong master.

Lý tưởng nhất, tôi muốn tất cả điều này xảy ra một cách kỳ diệu, với ít thông số hài hước và không thể làm được điều gì.

Có cách nào đơn giản để làm điều đó mà tôi bị thiếu không?

Tôi có thể nghĩ đến một cặp vợ chồng, nhưng tất cả đều yêu cầu tôi phải nhớ rằng tôi không muốn cam kết đó. Và đó chắc chắn không phải sở trường của tôi. Đặc biệt với các chương trình bị tấn công kém như vậy.

Nếu không, tôi quan tâm đến các cách phức tạp hơn, thủ công-ish để xử lý tình huống.

+0

Có, vâng, có. Lý tưởng nhất tôi nên refactor ứng dụng ngu ngốc. Ngay sau khi tôi được trả tiền để làm điều đó. (Và tôi có thể nghĩ đến một vài trường hợp khác, nơi mô hình như vậy sẽ có ý nghĩa, ngay cả trong các ứng dụng có cấu trúc tốt) – kch

+0

Đã thêm phản hồi cho nhận xét của bạn trong câu trả lời của tôi. – VonC

+0

Các tùy chọn khác: sử dụng một trong các phần mở rộng quilt (tội lỗi, xếp chồng lên nhau git, vv) và làm cho đổi tên của bạn một bản vá trong một hàng đợi. Tôi tin rằng các phần mở rộng này sẽ không cho phép bạn hợp nhất một bản vá chưa được tích hợp lại vào các cam kết thông thường, vì vậy bạn không thể vô tình hợp nhất nó. Vẫn không lý tưởng vì bạn cần nhớ bật rồi áp dụng lại vá mỗi lần bạn có các cam kết bình thường mới, nhưng bạn giải quyết vấn đề quên bạn không muốn cam kết đó. – quark

Trả lời

1

Giải pháp kỹ thuật (Git) sẽ sử dụng git attributes, sử dụng phối hợp thuộc tính.

merge 

Thuộc tính merge ảnh hưởng đến cách ba phiên bản của một tập tin được sáp nhập khi một tập tin cấp merge là cần thiết trong git merge.

Bạn sẽ tìm thấy trong câu hỏi SO "How do I tell git to always select my local version for conflicted merges on a specific file?" một ví dụ của việc sử dụng một thuộc tính như vậy, để buộc giữ phiên bản địa phương các tập tin nhất định khi sáp nhập vào một chi nhánh nhất định.

Vấn đề với thiết kết hợp các thuộc tính là các tập tin có chứa các đường dẫn có thể chứa mã thay đổi khác, mà tôi muốn sáp nhập

Đừng quên bạn có thể kết hợp bất kỳ loại kịch bản để quản lý những hòa trộn qua số git attributes. Điều đó bao gồm một kịch bản có thể giữ các thay đổi bạn muốn địa phương, trong khi hợp nhất phần còn lại. Sẽ phức tạp hơn khi viết một "trình quản lý hợp nhất" như vậy, nhưng nó là một cách hướng tới một giải pháp tự động đặc biệt.


Một giải pháp ít kỹ thuật sẽ để tách các cấu hình giá trị từ các tập tin cấu hình:

  • tập tin cấu hình chỉ chứa tên phải được thay thế
  • giá trị cấu hình là một số tệp (một tệp cho mỗi môi trường) với các giá trị thực tế cho mỗi tên.

Tập lệnh được sử dụng để thay thế tên trong tệp cấu hình thực bằng giá trị của một trong các tệp giá trị cấu hình cần thiết cho môi trường nhất định.

+0

Vấn đề với việc thiết lập các thuộc tính hợp nhất là các tệp có chứa các đường dẫn có thể chứa mã thay đổi khác, mà tôi muốn hợp nhất. Vì vậy, nó là nhiều hơn về một changeset thay vì toàn bộ tập tin. – kch

+0

Thú vị phản ứng, nhưng yea, có vẻ như rất nhiều rắc rối. – kch

3

Bạn có thể sử dụng git cherry pick để chỉ hợp nhất các bản vá bạn chọn. Chỉ cần anh đào chọn mọi cam kết ngoại trừ cam kết địa phương đối với chi nhánh chính.

+1

Tôi thích câu trả lời này, ngoại trừ: làm thế nào để bạn làm điều này nếu bạn có * nhiều * thay đổi? Có một mô hình một dòng để loại trừ một bản vá từ một bộ không? – quark

+0

Bằng cách tương tự, phần mở rộng ghép Mercurial có một lá cờ cho điều này: 'hg transplant -p local'. (Có rất nhiều đối số khác mà bạn cần để làm cho nó hoạt động, nhưng đây là những gì sẽ bỏ qua các changeset đã cho.) – quark

+0

@quark: Quá trình rebase tương tác có thể thực hiện điều đó. Các tính năng 'git checkout -b tmp && git rebase -i --onto dev dev tmp' sẽ đặt bạn vào một trình soạn thảo, nơi bạn có thể chọn các commit nào giữa' dev' và 'features' để đặt trên một nhánh mới' tmp' bắt đầu từ 'dev'. Bạn cũng có thể sử dụng nhiều cam kết thành một, và thậm chí là sắp xếp lại các cam kết nếu bạn cảm thấy thích mạo hiểm. –

0

Tôi sẽ thực hiện một lần rebase tương tác với chủ và di chuyển cam kết tên đường dẫn-sửa lỗi của bạn đến cuối. Sau đó, bạn có thể hợp nhất tới điểm đó. Chỉ cần tiếp tục di chuyển cam kết đặc biệt của bạn đến cùng.

Bạn cũng có thể thấy stash hữu ích. Thay vì thực sự cam kết sửa chữa tên đường dẫn, bạn có thể giấu chúng đi. Nếu thử phương pháp này, bạn có thể muốn xem câu hỏi trên How to reverse apply a stash.

+0

Vâng, nhưng điều đó không giúp tôi hợp nhất qua lại. Tôi đã cố gắng sử dụng stash trong một thời gian nhưng nó được nhàm chán thực sự nhanh chóng. Tốt hơn là rebase -i cam kết. – kch

0

Vâng, bởi vì không có câu trả lời cho đến nay cung cấp một giải pháp đơn giản, tôi sẽ giả những gì tôi muốn làm là không thể, và thêm vào đống giải pháp đôi khi hữu ích:

Nếu bạn luôn phát triển trên Chi nhánh features, sau đó bạn có thể hợp nhất features thành master và sau đó, trong master, git revert local. (Trường hợp local là thẻ tham chiếu đến cam kết mà bạn đã tùy chỉnh đường dẫn, vv cho môi trường cục bộ của bạn.)

Bây giờ bạn không bao giờ được hợp nhất master vào features.

Trong trường hợp này, master trở thành một nhánh triển khai, chỉ nhận được sự hợp nhất từ ​​các nhánh khác. (Lý tưởng nhất, chỉ từ chi nhánh features.)

Việc này rất dễ dàng, chỉ cần thêm một nhà phát triển khác vào luồng công việc và mọi thứ trở nên lộn xộn. Vẫn có thể được làm việc xung quanh bằng cách sử dụng các chiến lược hợp nhất rõ ràng, nhưng nó thường là một nỗi đau.

+0

Âm thanh như câu trả lời thực sự là sửa mã. Giải nén các đường dẫn mã hóa cứng vào một tệp cấu hình có thể được ghi đè bằng tệp cấu hình cục bộ. Theo dõi tệp cấu hình mặc định nhưng không phải tệp cấu hình cục bộ hoặc một thứ gì đó dọc theo các dòng đó. –

+0

Vâng, đó là lời khuyên tốt, nhưng hãy xem bình luận của tôi dưới câu hỏi của tôi. – kch

0

Tôi không biết nếu điều này sẽ làm việc, nhưng:

  1. Tạo một cam kết rằng, do "chủ" phiên bản của tập tin cấu hình, biến chúng thành phiên bản bạn cần tại địa phương. Lưu ý SHA-1. Chúng tôi sẽ gọi nó là MAKE_LOCAL
  2. Tạo một cam kết cho phiên bản tệp cấu hình cục bộ của bạn, biến chúng thành phiên bản phù hợp cho chính. Lưu ý SHA-1.Chúng tôi sẽ gọi nó là MAKE_REMOTE
  3. Sử dụng móc git, khi bạn cam kết:
    1. git cherry-pick MAKE_REMOTE (hoặc sử dụng git diffpatch)
    2. Cho phép các cam kết bắt
    3. git cherry-pick MAKE_LOCAL (hoặc sử dụng git diffpatch)

Tôi nghĩ có một wa tốt hơn nữa y chuyển đổi các tập tin theo cách này, nhưng tôi không thể nhớ lại (nếu bạn có thể tìm thấy bài trình bày giton của shacon từ RubyConf, và có thể lội qua 800 trang trình bày, trong đó có một số ví dụ tuyệt vời).

1

ok. này không được bảo đảm để làm việc mỗi thời gian, nhưng một cái gì đó như thế này có thể làm việc (và trong các trường hợp nó wont bạn sẽ có một thay đổi mâu thuẫn nào đó đã được giải quyết):

  • làm chi nhánh địa phương của bạn
  • làm địa phương -only thay đổi
  • tiếp tục phát triển

khi thực hiện hợp nhất để làm chủ:

  • rebase -i master từ chi nhánh của bạn và di chuyển thay đổi địa phương chỉ đến END của chuỗi vá.
  • giải quyết mọi xung đột trong quy trình. Nếu thay đổi cục bộ chỉ có trong các tập tin cấu hình và bạn không chạm vào chúng trong sự phát triển thường xuyên, thì bạn sẽ không có vấn đề gì. Nếu, nếu không, bạn có xung đột, thì đây là trường hợp khi bạn thực sự thay đổi trong cùng một khu vực và bạn cần chú ý để giải quyết.
  • kiểm tra ra chủ
  • sáp nhập của bạn địa phương ngành -1:

    git merge địa phương^

này sẽ để lại cho bạn với tổng thể có tất cả những thay đổi trên các địa phương ngoại trừ người cuối cùng một.

Nếu bạn có nhiều địa phương = chỉ thay đổi, tôi đề nghị bạn squash chúng cùng nhau trong khi rebase.

6

Giải pháp của tôi cho vấn đề này sử dụng rebase chứ không phải là hợp nhất

Bắt đầu với một cây cam như thế này:

a-b-c <-- master 
\ 
    d <-- local 
    \ 
    e-f-g <-- dev 

$ git rebase --onto chủ dev địa phương

 master 
     V 
    a-b-c-e'-f'-g' <-- dev 
    \ 
     d <-- local 

$ git checkout master

$ git merge dev

   master 
       V 
    a-b-c-e'-f'-g' <-- dev 
    \ 
     d <-- local 

$ git rebase --onto thạc sĩ bậc thầy địa phương

   master 
       V 
    a-b-c-e'-f'-g' <-- dev 
       \ 
       d' <-- local 

$ git branch -f dev địa phương

   master 
       V 
    a-b-c-e'-f'-g' 
       \ 
       d' <-- local 
       ^
       dev 
+2

OK.Bây giờ, làm thế nào về một liên kết tốt đến một nơi giải thích tất cả các phép thuật này? :) Tôi đã quét git-scm.com/book trước đó, nhưng tôi không có cơ sở để hiểu những gì bạn vừa làm. – oligofren

1

Cá nhân, nếu tôi phải làm một cái gì đó như thế này và đã cho bất cứ điều gì lý do ngăn chặn từ thông tin tái cấu trúc khi tôi đi, tôi sẽ thêm hai chi nhánh nữa, kết thúc bằng một sắp xếp tương tự như sau:

master: mã ban đầu bạn được thừa kế

localcred: nhánh từ chính và chỉ thêm một bản vá thay đổi tất cả thông tin xác thực thành những gì bạn cần tại địa phương. Hãy coi nhánh này là chỉ đọc sau đây (và có thể thêm một cái móc để ngăn chặn các cam kết tình cờ).

feature: chi nhánh từ thạc sĩ, và tất cả các bản sửa lỗi đi đây (và có thể thêm một cái móc để ngăn chặn việc sáp nhập với các bản vá trong localcred)

local: một chi nhánh (không phải là một thẻ!) Mà sẽ bắt đầu ra như là một chi nhánh của localcred, và sau đó hợp nhất tính năng bất cứ khi nào bạn cần chạy thử nghiệm đơn vị của bạn. Tất cả các thử nghiệm xảy ra từ đây, nhưng không có sự phát triển nào xảy ra ở đây. Ngoài ra, nhánh này là dùng một lần, vì bạn có thể muốn rebase bên trong feature và cách nhanh nhất để xử lý kết quả là xóa chi nhánh local, phân nhánh lại từ localcred và hợp nhất feature trước khi chạy thử nghiệm của bạn. Đây có thể là một hoạt động đủ phổ biến trong quy trình làm việc của tôi mà tôi xây dựng một bí danh để thực hiện nó lặp đi lặp lại chỉ trong một vài lần nhấn phím, nhưng tôi làm việc ra khỏi các chi nhánh của Git. xem tôi, YMMV.

Khi bạn nghĩ sửa của bạn đã sẵn sàng để công bố, bạn làm rebase cuối cùng của bạn của feature để làm sạch lịch sử, đổ và tạo local cho thử nghiệm cuối cùng của bạn, kết hợp feature vào master, và một khi đã chấp nhận thượng nguồn, sáp nhập master vào localcred và rebase đắp vá thông tin xác thực của bạn lên trên cùng, sau đó đổ và tạo lại localfeature và phát lại trò chơi.

Nếu bạn muốn kiểm tra nhanh các biến thể nhỏ của mã mà không phải cam kết và hợp nhất mỗi lần, hãy kiểm tra local, thực hiện thay đổi cho đến khi bạn hài lòng, cam kết và chọn ngay từ local thành feature , sau đó thả và tạo lại địa phương.

Điều đó có thỏa mãn nhu cầu của bạn không?

0

Câu hỏi là câu hỏi cũ nhưng tôi vẫn chưa tìm thấy câu trả lời hay. Hiện tại tôi đang đối mặt với cùng một vấn đề và dưới đây là giải pháp của tôi để giải quyết vấn đề này:

Có hai chi nhánh tại địa phương của tôi: masterlocal_settings. Sau khi cắt đứt chi nhánh local_settings từ master Tôi đã cam kết có tất cả đường dẫn cục bộ, không gắn thẻ và không cố nhớ chúng. Trong quá trình phát triển địa phương, tôi đã chuyển sang chi nhánh local_settings, vì vậy tôi có thể chạy một ứng dụng bằng các đường dẫn cục bộ. Nhưng khi đó là thời gian để cam kết tôi stash một nhà nước hiện tại và chuyển sang chi nhánh master. Sau đó, tôi bật các changeset stashed và cam kết nó vào master. Và bước cuối cùng là chuyển về local_settings, hợp nhất từ ​​master và tiếp tục phát triển. Tóm tắt lại: Tôi chỉ cam kết vào các chi nhánh local_settings chỉ những thay đổi sẽ được lưu trữ cục bộ và sẽ không bao giờ thành chủ; và không hợp nhất từ ​​local_settings đến master.

Bây giờ giả sử tôi cần thêm sửa đổi "tốt" vào tệp có đường dẫn cục bộ được thêm trước đó, nhưng sửa đổi "tốt" được yêu cầu trong chi nhánh master. Tôi thực hiện các thay đổi của mình khi bản sao làm việc là đầu dành cho local_settings, cất giữ và kiểm tra master. Stash giữ một changeset, có liên quan đến local_settings, mặc dù tôi đang ở trên master rồi. git stash pop áp dụng các thay đổi được lưu trữ cho bản sao làm việc và kết thúc có sự khác biệt so với bản gốc, nhưng chỉ với sửa đổi gần đây, không bao gồm đường dẫn cục bộ đã được thêm trước đó và không phải là một phần của thay đổi được lưu trữ gần đây. Do đó nó có thể được cam kết mà không gây rối đường dẫn trong chi nhánh master. Sau đó lại hợp nhất từ ​​master thành local_settings.

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