2010-01-08 27 views
15

Đây là tình huống. Tôi đang làm việc trên chi nhánh master. Tôi tạo file1 và commit. Tôi tạo file2 và cam kết. Rất tiếc. Tôi có thể muốn sử dụng file2, một ngày nào đó, nhưng nó chắc chắn không phải cái gì đó nên được đặt trong nhánh chính. Để tôi không bị mất tệp2, tôi sử dụnggit: Làm cách nào để ghi đè tất cả thay đổi cục bộ khi hợp nhất?

git checkout head~1 
git branch new-branch 
git checkout new-branch 

để tôi có thể tiếp tục phát triển. Tôi thêm tệp3 vào số new-branch. Nếu bạn đã chú ý, tôi có hai chi nhánh, master có chứa "file1" và "file2" và new-branch có chứa "file1" và "file3".

Bây giờ là lúc để có được những thay đổi tôi đã thực hiện lại vào nhánh chính. Cách tốt nhất để làm điều này là gì? Tôi chắc chắn muốn người đứng đầu chi nhánh master chỉ vào các tệp khi chúng xuất hiện trong new-branch, nhưng tôi cũng không muốn mất công việc tôi đã thực hiện trong tệp 2 bằng cách đặt lại, trong trường hợp tôi muốn sử dụng nó.

Hãy nhớ rằng đây là sự đơn giản hóa. Thay vì chỉ ba tập tin, tôi đã có một chục tập tin với hàng chục dòng mã được thay đổi trên tất cả các nơi với nhiều cam kết. Tôi chắc chắn hy vọng các giải pháp không phải là để làm một tập tin theo tập tin hợp nhất/kiểm tra, bởi vì đó sẽ là một nỗi đau rất lớn.

Bất kỳ ý tưởng nào?

+0

Bạn nói "Điều này trông giống như những gì tôi cần", nhưng bạn đã thử chuyển nhánh như tôi chỉ ra trong câu trả lời của tôi? – VonC

+0

Tôi đã làm. Câu trả lời của Randal thậm chí còn gần hơn với giải pháp của tôi. Nó chỉ ra chìa khóa là 'git reset --hard HEAD ~ 1'. Tôi đã không nhận ra bạn có thể thiết lập lại một chuỗi các cam kết với một lệnh. Tất cả những gì tôi cần làm là rẽ nhánh nhánh hiện tại, sau đó thiết lập lại nơi tôi bắt đầu trở nên tồi tệ. – kubi

Trả lời

3

Tôi đang làm việc trên nhánh chính. Tôi tạo tệp1 và cam kết.

date >file1 
git add file1 
git commit -m 'added file1' 

tôi tạo file2 và cam kết.

date >file2 
git add file2 
git commit -m 'added file2' 

Whoops. Tôi có thể muốn sử dụng tệp2, một ngày nào đó, nhưng chắc chắn không phải là thứ gì đó sẽ được đặt trong chi nhánh chính .

Rất tiếc. Rất đơn giản. Tạo chi nhánh mới từ nơi bạn ở:

git checkout -b savingfile2 

Điều này sẽ làm cho tệp 2 thay đổi cam kết cho savingfile2. Bây giờ quay trở lại và thư giãn một bước trên bậc thầy

git checkout master 
git reset --hard HEAD~1 

Tại thời điểm này, các cam kết dẫn đến tổng thể sẽ phản ánh việc bổ sung các file1, và thêm cam kết giữa chủ và savingfile2 sẽ là sự bổ sung của file2 đó .

Nếu bạn thực hiện nhiều thay đổi để làm chủ, và sau đó muốn mang file2 lại cuối cùng, bạn sẽ muốn rebase rằng phụ chi nhánh vào chủ mới:

date >file3 
git add file3 
git commit -m 'adding file3' 
date >file4 
git add file4 
git commit -m 'adding file4' 

Và bây giờ chúng tôi cuối cùng muốn file2:

git checkout savingfile2 
git rebase master # might need to fix conflicts here 
git checkout master 
git merge savingfile2 # will be a fast-forward 
git branch -d savingfile2 # no need any more 

Điều đó sẽ thực hiện.

+0

"git merge savingfile2 # sẽ chuyển nhanh" <- Điều gì về việc thêm '--ff-only' để đảm bảo nó? – weakish

+0

@weakish - tùy chọn đó mới hơn câu trả lời. :) –

1

gì bạn cần làm là những gì bạn nên làm khi bạn nhận thấy sai lầm của bạn của commiting file2: undo cam kết (thay vì tạo ra một chi nhánh mới):

git checkout master 
git reset HEAD^ 

này lá file2 untracked và không hề hấn gì và có thể sửa đổi không phổ biến. Sau đó, bạn nên (có) stash (ed) sửa đổi uncommited trong trường hợp bạn muốn sử dụng chúng sau:

git stash save "modifications that should not be in the master branch" 

stashing được thoát khỏi bất kỳ thay đổi địa phương, cho phép master được thực hiện điểm đến new-branch:

git merge new-branch 

Mục tiêu ở đây là để loại bỏ sự phân kỳ giữa hai nhánh, tức là tạo master một tổ tiên của new-branch. Bằng cách này, không có sự hợp nhất thực sự nào sẽ xảy ra và lệnh cuối cùng chỉ cần nhanh về phía trước chi nhánh master (miễn là không có thay đổi cục bộ nào).

+0

Làm cách nào để làm việc này nếu tôi đã thực hiện nhiều cam kết trên nhánh chính của mình trước khi nhận thấy? 'git reset' sẽ quay lại HEAD, không để tôi di chuyển những cam kết không đúng, đúng không? – kubi

+0

Bạn có thể sử dụng (tương tác) 'rebase' để xóa các cam kết tùy ý từ dọc theo lịch sử cam kết (trái với' git reset') miễn là các cam kết đó chưa được đẩy vào bất kỳ đâu. –

1

Vì bạn không theo dõi optimal workflow được mô tả bởi Tomi Kyöstilä, nhưng cũng vì bạn chưa xuất bản (đẩy) bất kỳ thứ gì, tại sao không chuyển đổi hai nhánh?
(được cung cấp tất cả mọi thứ là cam kết)

masternew-branch chỉ là một số gợi ý để một số SHA1:

$ git checkout master    #start from master 
$ git branch tmp     # tmp points on master HEAD 
$ git checkout new-branch   # switch to new-branch 
$ git branch -f master new_branch # master points at new-branch HEAD 
$ git checkout tmp     # switch back to *former* master branch 
$ git branch -f new_branch tmp  # new-branch points at former master HEAD 
$ git checkout master    # go to new master 
$ git branch -D tmp    # remove tmp pointer 

... và bạn đã hoàn tất.
(từ chối trách nhiệm: không kiểm tra được nêu ra, vì vậy hãy thử nó một cách thận trọng;))

Xem:

+0

Điều này trông giống như những gì tôi cần. Cảm ơn! – kubi

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