Làm cách nào để hợp nhất các thay đổi không được cam kết tại địa phương của tôi vào một nhánh Git khác?


621

Làm thế nào tôi có thể làm như sau trong Git?

Chi nhánh hiện tại của tôi là chi nhánh1 và tôi đã thực hiện một số thay đổi cục bộ. Tuy nhiên, bây giờ tôi nhận ra rằng tôi thực sự muốn áp dụng những thay đổi này cho nhánh2. Có cách nào để áp dụng / hợp nhất những thay đổi này để chúng trở thành thay đổi cục bộ trên nhánh2 mà không cần thực hiện chúng trên nhánh1 không?


2
Có một Hướng dẫn Git tuyệt vời ngay tại đây trên SO. Đây là một loại trung tâm cho tất cả các câu hỏi git trên stack stack.
Decio Lira

Câu trả lời:


898

Vì các tệp của bạn chưa được cam kết trong branch1:

git stash
git checkout branch2
git stash pop

hoặc là

git stash
git checkout branch2
git stash list       # to check the various stash made in different branch
git stash apply x    # to select the right one

Theo nhận xét của benjohn (xem git stashtrang nam ):

Để cũng stash các tệp hiện chưa được theo dõi (mới được thêm), hãy thêm đối số -u, vì vậy:

git stash -u

2
Không có gì. Thêm ví dụ về sử dụng stash tại unethicalblogger.com/posts/2008/11/ .
VonC

2
Nếu bạn đang tìm kiếm một giải pháp cho cùng một vấn đề nhưng với TFS, giải pháp tương đương là tạm gác các thay đổi của bạn, sau đó sử dụng TFS Power Tools để chuyển sang nhánh chính xác bằng cách sử dụng công tắc / di chuyển.
xr280xr

1
Điều này làm việc cho tôi. Tuy nhiên, tôi cũng phải tạo một chi nhánh địa phương để 'stash pop' hoạt động. Hãy kiểm tra stackoverflow.com/questions/1783405/git-checkout-remote-branch nếu có điều gì đó tương tự đang xảy ra với bạn.
mimoralea

21
Để cũng stash các tệp hiện chưa được theo dõi (mới được thêm) , hãy thêm đối số -u, vì vậy : git stash -u.
Stewohn 24/07/2015

2
@Benjohn Điểm tốt. Tôi đã bao gồm nhận xét của bạn trong câu trả lời để dễ nhìn hơn.
VonC

84

Stashing, cam kết tạm thời và nổi loạn tất cả có thể là quá mức cần thiết. Nếu bạn chưa thêm các tệp đã thay đổi vào chỉ mục, thì bạn có thể chỉ cần kiểm tra chi nhánh khác.

git checkout branch2

Điều này sẽ hoạt động miễn là không có tệp nào bạn đang chỉnh sửa khác nhau giữa nhánh1 và nhánh2. Nó sẽ để lại cho bạn trên nhánh2 với những thay đổi làm việc được bảo tồn. Nếu chúng khác nhau thì bạn có thể chỉ định rằng bạn muốn hợp nhất các thay đổi cục bộ của mình với các thay đổi được giới thiệu bằng cách chuyển đổi các nhánh với -mtùy chọn thanh toán.

git checkout -m branch2

Nếu bạn đã thêm các thay đổi vào chỉ mục thì trước tiên bạn sẽ muốn hoàn tác các thay đổi này bằng cách đặt lại. (Điều này sẽ giữ bản sao làm việc của bạn, nó sẽ chỉ loại bỏ các thay đổi theo giai đoạn.)

git reset

3
Tôi nghĩ rằng stash "đơn giản hơn" bằng cách nào đó để hiểu, nhưng cách tiếp cận của bạn tốt hơn là tính đến thư mục làm việc trên các chi nhánh khác nhau. +1
VonC

6
Một kiểm tra truyền thống đơn giản có vẻ phù hợp hơn với vấn đề trong tay. kiểm tra là trọng lượng nhẹ hơn, nó chỉ cập nhật các tập tin cần thay đổi. Có lẽ dễ hiểu hơn về cách tiếp cận stash, hoặc có thể là nó không đủ rõ ràng rằng thanh toán là 'an toàn' trong trường hợp sử dụng này.
CB Bailey

Nếu checkout -mkhông "an toàn" trong một số trường hợp (có thể nó sẽ gây ra xung đột hợp nhất), thì stash có cung cấp bất kỳ lợi thế nào không (ví dụ: bạn có thể hủy bỏ pop stash không)?
Craig McQueen

1
@craigMcQueen Bạn không thể hủy bỏ một stash popped nhưng stash sẽ phàn nàn về xung đột khi bạn bật nó. Bạn có thể sửa các xung đột và sau đó cam kết, nhưng bản gốc vẫn còn trên ngăn xếp trong trường hợp này! :)
Shaun F

Trong trường hợp có xung đột hợp nhất, các tệp không được sao lưu là .orig?
vui vẻ

13

Một thay thế ngắn hơn cho phương pháp stash đã đề cập trước đó sẽ là:

Tạm thời di chuyển các thay đổi thành một stash.

  1. git stash

Tạo và chuyển sang một nhánh mới và sau đó bật stash cho nó chỉ trong một bước.

  1. git stash branch new_branch_name

Sau đó, chỉ addcommitnhững thay đổi cho chi nhánh mới này.


10

CẢNH BÁO: Không dành cho người mới git.

Điều này xuất hiện đủ trong quy trình làm việc của tôi mà tôi gần như đã cố gắng viết một lệnh git mới cho nó. git stashDòng chảy thông thường là con đường để đi nhưng có một chút khó xử. Tôi thường thực hiện một cam kết mới trước vì nếu tôi đã xem xét các thay đổi, tất cả thông tin đều mới mẻ trong tâm trí tôi và tốt hơn là chỉ bắt đầu git commitnhững gì tôi tìm thấy (thường là một lỗi thuộc về chủ nhân mà tôi phát hiện ra khi làm việc trên tính năng chi nhánh) ngay lập tức.

Nó cũng rất hữu ích nếu bạn gặp phải những tình huống như thế này rất nhiều để có một thư mục làm việc khác cùng với thư mục hiện tại của bạn luôn có masterchi nhánh được kiểm tra.

Vì vậy, làm thế nào tôi đạt được điều này như thế này:

  1. git commit những thay đổi ngay lập tức với một thông điệp cam kết tốt.
  2. git reset HEAD~1 để hoàn tác các cam kết từ chi nhánh hiện tại.
  3. (tùy chọn) tiếp tục làm việc trên tính năng.

Đôi khi sau đó (không đồng bộ) hoặc ngay lập tức trong cửa sổ đầu cuối khác:

  1. cd my-project-master đó là một WD khác chia sẻ tương tự .git
  2. git reflog để tìm lỗi tôi vừa thực hiện.
  3. git cherry-pick SHA1 của cam kết.

Sau đó, tùy chọn (vẫn không đồng bộ), sau đó bạn có thể khởi động lại (hoặc hợp nhất) nhánh tính năng của mình để nhận lỗi, thường là khi bạn sắp gửi PR và đã xóa sạch nhánh tính năng của mình và WD:

  1. cd my-project WD chính mà tôi đang làm việc.
  2. git rebase master để có được các lỗi.

Bằng cách này, tôi có thể tiếp tục làm việc trên các tính năng không bị gián đoạn và không phải lo lắng về git stash-ing bất cứ điều gì hoặc phải làm sạch WD của tôi trước một git checkout(và sau đó có việc kiểm tra các tính năng backout chi nhánh một lần nữa.) Và vẫn có tất cả các sửa lỗi của tôi đi vào masterthay vì ẩn trong nhánh tính năng của tôi.

IMO git stashgit checkoutlà một PIA thực sự khi bạn đang làm việc trên một số tính năng lớn.


Thú vị và thay thế hợp lệ cho câu trả lời của tôi. +1
VonC

Bạn đến từ đồng bóng? Việc my-project-masterchia sẻ giống nhau .gitlàm cho nó nghe như nó. Tại sao không git checkout -b bugfixABC; git commit -a; git reset HEAD^ --hard, sau đó (không đồng bộ) trong khi master, git cherry-pick <SHA1 of the commit(s) in bugfixABC? (hoặc thậm chí, để tránh phải tìm ra SHA1, git rebase --onto master feature bugfixABCtừ bất cứ nơi nào bạn đang ở. Điều đó có nghĩa là bạn có thể làm điều đó trực tiếp sau khi git resetở trên, trong khi trên feature.)
Gauthier

Tuy nhiên, OP có vẻ như họ chưa sẵn sàng để thực hiện các thay đổi, trong trường hợp đó checkout -mlà tốt hơn.
Gauthier

2

Nếu đó là về những thay đổi đã cam kết, bạn nên xem git-rebase, nhưng như đã nêu trong nhận xét của VonC, vì bạn đang nói về những thay đổi cục bộ, git-stash chắc chắn sẽ là cách tốt để làm điều này.


Tôi không hiểu giải pháp này: nó sẽ viết lại lịch sử cam kết của nhánh2 từ nhánh1 ... tại sao nhận tất cả các thay đổi đã cam kết từ nhánh1 trong nhánh2 khi chúng tôi chỉ muốn nhận các thay đổi không cam kết cục bộ của nhánh1 trong nhánh2? ...
VonC

@VonC: đã đồng ý, trong trường hợp này, rebase nhận được tất cả các thay đổi đã cam kết kể từ lần hợp nhất cuối cùng giữa các nhánh thành nhánh1. Lúc đầu tôi không nhận được thông số "không cam kết" của câu hỏi này. rebase không phải là câu trả lời hay.
claf

@claferri: pfew ... Tôi bắt đầu đau đầu;) Tôi sẽ đánh giá thấp câu trả lời của bạn, nhưng vì tôi đã tự xuất bản một câu, nên có một "xung đột lợi ích rõ ràng". Với bài đăng được cập nhật của bạn, bây giờ tôi không phải tải xuống. Cảm ơn :)
VonC

@VonC: lần sau, vui lòng bỏ phiếu miễn là câu trả lời của tôi sai như câu này;)
claf

1

Các câu trả lời được đưa ra cho đến nay không lý tưởng bởi vì chúng đòi hỏi rất nhiều công việc không cần thiết để giải quyết xung đột hợp nhất, hoặc chúng đưa ra quá nhiều giả định thường sai. Đây là cách để làm điều đó một cách hoàn hảo. Liên kết là trang web của riêng tôi.

Làm thế nào để cam kết với một chi nhánh khác trong git

Bạn có những thay đổi không được cam kết my_branchmà bạn muốn cam kết master, mà không cam kết tất cả các thay đổi từ đó my_branch.

Thí dụ

git merge master
git stash -u
git checkout master
git stash apply
git reset
git add example.js
git commit
git checkout .
git clean -f -d
git checkout my_branch
git merge master
git stash pop

Giải trình

Bắt đầu bằng cách sáp nhập mastervào chi nhánh của bạn, vì cuối cùng bạn sẽ phải làm điều đó và bây giờ là thời điểm tốt nhất để giải quyết mọi xung đột.

Các -utùy chọn (aka --include-untracked) trong git stash -ungăn chặn bạn khỏi mất file untracked khi sau này bạn làm git clean -f -dtrong vòng master.

Sau git checkout masterđó, điều quan trọng là bạn KHÔNG git stash pop, bởi vì bạn sẽ cần stash này sau. Nếu bạn bật stash tạo ra trong my_branchvà sau đó làm git stashtrong master, bạn sẽ gây ra xung đột nhập không mong muốn khi sau đó bạn áp dụng stash rằng trong my_branch.

git resetunstages tất cả mọi thứ kết quả từ git stash apply. Ví dụ: các tệp đã được sửa đổi trong ngăn chứa nhưng không tồn tại trong masterđược dàn dựng là xung đột "bị xóa bởi chúng tôi".

git checkout .git clean -f -dloại bỏ mọi thứ không được cam kết: tất cả các thay đổi đối với các tệp được theo dõi và tất cả các tệp và thư mục chưa được theo dõi. Chúng đã được lưu trong ngăn chứa và nếu để lại mastersẽ gây ra xung đột hợp nhất không cần thiết khi chuyển trở lại my_branch.

Cái cuối cùng git stash popsẽ dựa trên bản gốc my_branch, và do đó sẽ không gây ra bất kỳ xung đột hợp nhất nào. Tuy nhiên, nếu stash của bạn chứa các tệp chưa được bẻ khóa mà bạn đã cam kết làm chủ, git sẽ phàn nàn rằng nó "Không thể khôi phục các tệp không bị theo dõi từ stash". Để giải quyết mâu thuẫn này, xóa các tập tin từ cây làm việc của bạn, sau đó git stash pop, git add .git reset.


2
Câu trả lời của bạn không bị xóa vì nó được liên kết với trang web của bạn, nó đã bị xóa vì nó giống hệt với câu trả lời khác từ một tài khoản khác. Tôi thấy rằng tài khoản kia có cùng hồ sơ với bạn, bạn có đang sử dụng hai tài khoản không? Bạn có thể hợp nhất cả hai tài khoản. Ngoài ra, gắn cờ một mod để giải thích tình huống và bạn có thể nhận được câu trả lời ban đầu của mình (với upvote).

1
Bạn không thể tách chúng ra nếu chúng được hợp nhất, nhưng bạn được phép có nhiều tài khoản, miễn là bạn không sử dụng chúng để thực hiện hành vi gian lận bỏ phiếu (hoặc nói chung chúng tương tác với nhau). Giải thích tình huống của bạn cho một mod. Ngoài ra, việc xóa là một sai lầm trung thực, làm thế nào bạn có thể mong đợi bất cứ ai nói rằng bạn đang sử dụng hai tài khoản khác nhau?

3
Bạn cần gắn cờ bài đăng của mình và sử dụng tùy chọn Khác để thu hút sự chú ý của mod, họ sẽ không chú ý đến khi bạn chỉnh sửa câu trả lời đã xóa của bạn. Tôi đã gắn cờ bài đăng của bạn để chú ý mod, nhưng chúng khá bận rộn, vì vậy hãy kiên nhẫn, cuối cùng chúng sẽ đến với bạn.

1
Không đăng nội dung trùng lặp, đặc biệt là từ các tài khoản khác nhau. Bỏ phiếu hoặc gắn cờ để đóng thành hai bản sao nếu hai câu hỏi giống nhau.
Bill Lizard
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.