2010-09-19 10 views
11

Tôi đã tạo một Chi nhánh mới trước khi bắt đầu phát triển thử nghiệm. Tôi thường quên rằng (đó không phải là một vấn đề), nhưng bây giờ tôi đã làm nó trước.
Kể từ đó, tôi đã cập nhật 3 tệp.GIT: cam kết thay đổi chi nhánh cũ/an toàn trong khi ở chi nhánh mới/bẩn/dev mà không cần kiểm tra hoặc mất dữ liệu không bị chặn

  • Trong 2 chỉ là những thay đổi thử nghiệm mà tôi KHÔNG MUỐN cam kết với chi nhánh an toàn.
  • Trong 1 chỉ là những thay đổi an toàn (nhỏ) mà tôi chắc chắn KHÔNG muốn cam kết với chi nhánh an toàn. Tôi cũng tốt với những thay đổi cuối cùng này để được cam kết với chi nhánh mới (nhưng không phải).

Có thể - tôi chắc chắn - để (nhanh) cam kết một vài thay đổi không được cam kết, không được cam kết từ thư mục làm việc (bẩn) của tôi đến một chi nhánh cũ, an toàn? Điều duy nhất tôi có thể nghĩ là chuyển nhánh (không cần thanh toán), cam kết thay đổi trong 1 tệp và chuyển trở lại, nhưng tôi không biết điều gì sẽ xảy ra với những thay đổi khi chuyển về nhánh bẩn (họ vẫn còn ở đó hoặc họ đã 'biến mất' do cam kết?) ...

Tôi chắc GIT có điều gì đó đẹp cho điều này, nhưng GIT có rất nhiều, tôi không thể tìm thấy chính xác điều tương tự.
(Tôi đã sử dụng this 'manual' for help nhưng tôi không chắc chắn chính xác điều tương tự ở trong đó. Nếu đó là (và bạn sẵn sàng quét nội dung), hãy cho tôi biết, vì vậy tôi biết thời gian tới để xem khó hơn.)

Cảm ơn! Bây giờ tôi sẽ chỉ giữ một mẩu giấy tiện dụng với những thay đổi 'để cam kết với chi nhánh an toàn sau này'.

Trả lời

6

Vì vậy, tình hình của bạn là

x--x--x (safe) 
     \ 
     <a,b,c> (3 private evolutions in exp branch) 

Và bạn muốn đi đến

x--x--x--a (a committed only in safe banch) 
     \ 
     b,c (b and c commited in exp branch) 

Bạn có thể:

git add a 
git commit -m  # in exp branch, gasp! 
git stash save  # save the rest of the exp work in progress 
git checkout master 
git merge exp  # fast-forward merge 

x--x--x--a (safe,exp) 
      \ 
      [b,c] (stashed) 

git branch -f exp HEAD~1 # reset branch exp to before 'a' 
git checkout exp 
git stash pop 
git add -A 
git commit -m "..." 

x--x--x--a (a committed only in safe banch) 
     \ 
     b,c (b and c commited in exp branch) 
+2

Vì thanh toán không chạm vào các tệp đã sửa đổi, sẽ không thể chỉ là 'checkout master; thêm một; cam kết; thanh toán exp' và tiếp tục? Giả sử rằng các thay đổi không được tổ chức. – rlduffy

+0

@rlduffy: nó sẽ hoạt động. Tôi luôn có xu hướng cẩn thận hơn với các thiết bị chuyển mạch nhánh. – VonC

+0

Nếu ‘exp’ cam kết vượt quá ‘safe’ (tôi không thể quyết định điều này từ mô tả của OP) thì bạn sẽ không muốn 'git checkout safe && git merge exp' vì nó sẽ kéo theo các cam kết khác. Nếu bạn chỉ muốn cắt giảm ‘a’ của ‘exp’, thì tôi sẽ chỉ chọn món anh ta vào 'an toàn' thay vì sáp nhập nó. –

0

Kể từ nhánh hoạt động trên GIT là giá rẻ như vậy, tôi sẽ chỉ sử dụng quy trình làm việc sau:

  • Tạo một chi nhánh mới ra chi nhánh của bạn "thử nghiệm"
  • cam kết bất cứ điều gì file unstaged cần
  • quay trở lại để làm chủ
  • cherrypick bất cứ cam kết từ "thử nghiệm" & chi nhánh mới của bạn vừa tạo ở bước 1.
  • quay trở lại chi nhánh "thử nghiệm"
7

không có cách nào để thêm một cam kết một chi nhánh xen kẽ với git commit. Có nhiều cách để sử dụng lệnh “đường ống dẫn nước” ở mức độ thấp để thực hiện chính xác những gì bạn mô tả, nhưng giao diện được hình thành bởi các lệnh này không được thiết kế để sử dụng tương tác . Có những cách chắc chắn để làm những gì bạn muốn; tùy thuộc vào các chi tiết của những thay đổi của bạn và nội dung của các chi nhánh liên quan đến nó có thể khá đơn giản.

The Easy điển hình: Chỉ cần sử dụng git checkout

Khi chuyển ngành, git checkout mà vẫn duy trì những thay đổi không bị giam hoặc từ chối chuyển đổi (trừ khi bạn sử dụng --force, --merge, hoặc --conflict). Vì vậy, miễn là các thay đổi không được cam kết của bạn chỉ chạm vào các tệp giống nhau ở cả HEAD (nhánh hiện tại) và nhánh đích của bạn, git checkout sẽ để lại những thay đổi đó trong chỉ mục và/hoặc cây đang hoạt động trong khi chuyển đổi nhánh. Nếu thay đổi không bị giam của bạn đáp ứng điều kiện này thì bạn có thể làm điều này:

git checkout safe-branch 
git add -- files-with-safe-changes 
git commit 
git checkout - 

Bạn cũng có thể sử dụng git add --patch đến giai đoạn và chỉ cam kết một số thay đổi trong các tập tin.

Sau đó, "thay đổi an toàn" của bạn sẽ là một phần của "an toàn"; chuyển về chi nhánh ban đầu của bạn sẽ "bỏ chúng lại" (hãy nhớ rằng, git checkout chỉ giữ lại các thay đổi không được cam kết khi chuyển nhánh).

Nếu các thay đổi khác của bạn phụ thuộc vào “thay đổi an toàn”, bạn có thể cần phải hợp nhất “nhánh an toàn” vào nhánh đang hoạt động của bạn (hoặc tùy thuộc vào quy trình làm việc của bạn). '). Để thực hiện điều này, bạn sẽ phải giấu các thay đổi không được cam kết của bạn (vì cả việc hợp nhất và rebase sẽ từ chối hoạt động nếu có những thay đổi không được cam kết).

git stash save 
git merge safe-branch 
git stash pop --index 

Nếu những thay đổi khác của bạn không phụ thuộc vào sự “thay đổi an toàn”, sau đó bạn có lẽ không nên bận tâm với một hợp nhất hoặc rebase. Cuối cùng, bạn sẽ hợp nhất các chi nhánh này lại với nhau (ví dụ: bằng cách hợp nhất chúng thành một nhánh ‘qa’ để thử nghiệm trước khi phát hành), nhưng không có lý do gì để hợp nhất chúng sớm.

Tuy nhiên dễ dàng, nhưng một chút mạo hiểm: git checkout -m

Nếu là người đầu tiên git checkout phàn nàn “Bạn phải thay đổi địa phương để some‑file; không chuyển đổi chi nhánh. ”, điều đó có nghĩa là bạn có các thay đổi chưa được sửa đổi đối với some-file và tệp khác với các mẹo của‘ chi nhánh an toàn ’và chi nhánh hiện tại của bạn; bạn sẽ cần một cách tiếp cận khác.

Nếu bạn tự tin rằng những thay đổi sẽ được áp dụng sạch lên phiên bản của some‑file đó là trong 'an toàn ngành', sau đó bạn có thể sử dụng tùy chọn -m/--merge nói git checkout để cố gắng thích nghi với những thay đổi để chúng áp dụng cho các tệp trong 'an toàn' chi nhánh '. Nếu hợp nhất không thể được thực hiện một cách sạch sẽ, thì bạn sẽ kết thúc với một cuộc xung đột hợp nhất và có thể khó khôi phục các thay đổi ban đầu của bạn (đây là lý do tại sao tôi gọi nó là "nguy hiểm").

an toàn: git stash + git checkout -m

Vì bạn thực sự chỉ muốn di chuyển một tập hợp con của những thay đổi trở lại ‘an toàn ngành’, nó có thể là tốt hơn để tập trung vào chỉ những thay đổi đó. Một phương pháp là sử dụng git stash để tạm thời lưu các thay đổi hiện tại của bạn để bạn không phải kéo tất cả chúng trở lại 'an toàn' chi nhánh '(và sau đó kéo một số/hầu hết trong số chúng trở lại nhánh đang hoạt động của bạn).

git stash save 
git checkout stash -- files-with-save-changes 
git checkout -m safe-branch 
git commit 
git checkout - 
git stash pop --index 

Các biến thể khác có thể thực hiện được. Bạn có thể sử dụng git checkout -p stash -- files để chỉ chọn một số thay đổi trong các tệp đó. Nếu không có thay đổi theo từng giai đoạn, thì trước tiên bạn có thể đặt “thay đổi an toàn”, git add -- files (một lần nữa, tùy chọn với -p), sử dụng git stash save --keep-index, chuyển đổi nhánh (có hợp nhất) và sau đó cam kết (tức là thay thế git checkout stash -- files bằng tiền -ảnh báo “thay đổi an toàn” và git stash --keep-index).

Trong tình huống này, tôi xem xét git checkout -m để được an toàn vì chúng tôi sử dụng git stash để duy trì một bản sao của những thay đổi hiện hành; nếu nỗ lực kết hợp ba chiều dẫn đến lộn xộn vô vọng, thì bạn có thể dễ dàng từ bỏ ý tưởng đưa "thay đổi an toàn" vào 'an toàn' chi nhánh 'và trở lại làm việc: chuyển về nhánh ban đầu và bật stash (git checkout -f - && git stash pop).

Một lần nữa, nếu các thay đổi khác của bạn phụ thuộc vào "thay đổi an toàn" thì bạn sẽ cần hợp nhất hoặc rebase. Bạn cũng có thể làm điều này trước khi popping stash (vì bạn cần một chỉ số rõ ràng và cây làm việc để làm việc hợp nhất/rebase).

Nếu bạn sẽ không hợp nhất nhánh làm việc của bạn với (hoặc rebase nó lên) ngay lập tức 'an toàn' chi nhánh, sau đó bạn có thể muốn hoàn tác "thay đổi an toàn" sau khi bạn bật stash (" thay đổi an toàn ”đã được lưu trong stash gốc và có thể bạn không muốn kết thúc bằng các cam kết thực hiện các thay đổi tương tự từ đầu trong hai chi nhánh khác nhau). Một khi bạn đã bật stash, sử dụng git checkout -- files-with-safe-changes để hoàn nguyên các tệp đó về phiên bản ở đầu nhánh đang hoạt động.


Các “hệ thống ống nước” giao diện được thiết kế để sử dụng trong kịch bản. Nó sẽ là cồng kềnh để sử dụng chúng trực tiếp trên dòng lệnh. Các phiên bản đầu tiên của git commit (và hầu hết các lệnh Git khác) là các kịch bản lệnh shell dựa trên giao diện này. Chúng vẫn có thể được viết như các kịch bản shell ngày nay, nhưng các phiên bản C thường nhanh hơn nhiều. Các bước cần thiết để cam kết với chi nhánh thay thế là:
thiết lập chỉ mục thay thế dựa trên cây ở đầu “nhánh an toàn”,
cập nhật chỉ mục với thay đổi “an toàn” (nếu thay đổi có thể không được áp dụng sạch sẽ? nó là tốt đẹp để có một cây làm việc để cho người dùng giải quyết các xung đột),
viết chỉ mục ra làm đối tượng cây,
tạo đối tượng cam kết mới trỏ đến cây mới và có mẹo hiện tại của “chi nhánh an toàn” với tư cách là phụ huynh của nó,
cập nhật "nhánh an toàn" để trỏ đến cam kết mới.

Không có gì về mặt kỹ thuật sai với cam kết của bạn “thay đổi an toàn” trong hai chi nhánh, nhưng nó thường là một ý tưởng tốt để đảm bảo mỗi thay đổi bắt nguồn từ chỉ một nơi duy nhất.

+0

Tôi thích hệ thống ống nước và các chi tiết. +1 – VonC