Git: Tạo một nhánh từ các thay đổi chưa được thực hiện / không được cam kết trên bản gốc


991

Bối cảnh: Tôi đang làm việc trên tổng thể thêm một tính năng đơn giản. Sau vài phút tôi nhận ra nó không đơn giản như vậy và tốt hơn là nên làm việc trong một chi nhánh mới.

Điều này luôn xảy ra với tôi và tôi không biết làm thế nào để chuyển sang một chi nhánh khác và thực hiện tất cả những thay đổi không được cam kết này khi tôi rời khỏi chi nhánh chính. Tôi nghĩ git stash && git stash branch new_branchđơn giản là sẽ hoàn thành điều đó nhưng đây là những gì tôi nhận được:

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ echo "hello!" > testing 

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git stash
Saved working directory and index state WIP on master: 4402b8c testing
HEAD is now at 4402b8c testing

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ git stash branch new_branch
Switched to a new branch 'new_branch'
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (db1b9a3391a82d86c9fdd26dab095ba9b820e35b)

~/test $ git s
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git checkout master
M   testing
Switched to branch 'master'

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

Bạn có biết có cách nào để thực hiện điều này không?


1
Mặc dù có một giải pháp đơn giản hơn cho vấn đề của bạn, bạn có thể chỉ định kết quả bạn nhận được khác với những gì bạn muốn không?
Gauthier

2
bằng cách thực hiện các câu trả lời ở trên hoặc ở phía dưới, những thay đổi không được cam kết nằm ở cả chủ và nhánh mới. Tôi chỉ muốn chúng trên nhánh mới, vì vậy tôi có thể kiểm tra chủ và làm việc với một thứ khác mà không có những thay đổi này trôi nổi xung quanh
knoopx

1
xem câu trả lời chỉnh sửa của tôi. Bạn cần phải thực hiện các thay đổi cục bộ của mình trên nhánh mới nếu bạn muốn kiểm tra một bản gốc sạch. Thay đổi cục bộ chỉ là sự khác biệt giữa ĐẦU hiện tại và các tệp của bạn trên đĩa. Những thay đổi trên tệp cục bộ không được phiên bản, bạn cần nói với git để lưu chúng ở đâu đó nếu bạn muốn truy xuất chúng sau này.
Gauthier

Câu trả lời:


1207

Không cần stash.

git checkout -b new_branch_name

không chạm vào những thay đổi cục bộ của bạn. Nó chỉ tạo ra nhánh từ ĐẦU hiện tại và đặt ĐẦU ở đó. Vì vậy, tôi đoán đó là những gì bạn muốn.

--- Chỉnh sửa để giải thích kết quả của chủ thanh toán ---

Bạn có bối rối vì checkout masterkhông loại bỏ những thay đổi của bạn?

Vì các thay đổi chỉ mang tính cục bộ, git không muốn bạn mất chúng quá dễ dàng. Khi thay đổi chi nhánh, git không ghi đè lên các thay đổi cục bộ của bạn. Kết quả của bạn checkout masterlà:

M   testing

, có nghĩa là các tập tin làm việc của bạn không sạch sẽ. git đã thay đổi CHÍNH, nhưng không ghi đè lên các tệp cục bộ của bạn. Đó là lý do tại sao trạng thái cuối cùng của bạn vẫn hiển thị các thay đổi cục bộ của bạn, mặc dù bạn đang bật master.

Nếu bạn thực sự muốn loại bỏ các thay đổi cục bộ, bạn phải buộc thanh toán với -f.

git checkout master -f

Vì những thay đổi của bạn không bao giờ được cam kết, bạn sẽ mất chúng.

Cố gắng quay trở lại chi nhánh của bạn, cam kết thay đổi của bạn, sau đó kiểm tra lại chủ.

git checkout new_branch
git commit -a -m"edited"
git checkout master
git status

Bạn sẽ nhận được một Mtin nhắn sau lần thanh toán đầu tiên, nhưng sau đó không còn nữa checkout mastergit statussẽ không hiển thị các tệp sửa đổi.

--- Chỉnh sửa để xóa nhầm lẫn về thư mục làm việc (tệp cục bộ) ---

Trả lời bình luận đầu tiên của bạn, những thay đổi cục bộ chỉ là ... tốt, cục bộ. Git không tự động lưu chúng, bạn phải bảo nó lưu lại sau. Nếu bạn thực hiện thay đổi và không cam kết rõ ràng hoặc bỏ qua chúng, git sẽ không phiên bản chúng. Nếu bạn thay đổi HEAD ( checkout master), các thay đổi cục bộ sẽ không bị ghi đè kể từ khi chưa được lưu.


32
Điều khó hiểu ở đây là, trang man của git nói rằng git checkoutcác tập tin Cập nhật trong cây làm việc để khớp với phiên bản trong chỉ mục hoặc cây được chỉ định. Đó là giả định các thay đổi trong hệ thống tập tin của bạn sẽ được GONE sau đó. Không có bất kỳ cơ hội để có được chúng trở lại. Ngay cả khi bạn nói họ sẽ không, điều này vẫn để lại một cảm giác rất tồi tệ. Tôi không tin tưởng điều này cả . Tài liệu thực sự xấu hoặc hành vi mặc định của git thực sự nguy hiểm. Người ta không cần phải tin tưởng vào một số heuristic của máy tự động hóa để phát hiện ra rằng trong trường hợp này bạn không muốn mất các thay đổi của mình.
Evi1M4chine

16
Nếu bạn đang kiểm tra một cam kết sẽ ghi đè lên các thay đổi cục bộ của bạn (nếu lịch sử giữa cam kết hiện tại và cam kết đích chạm vào các tệp được sửa đổi cục bộ của bạn), git sẽ từ chối. Chỉ khi checkoutkhông xung đột với các thay đổi cục bộ của bạn, thanh toán mới hoạt động và để lại các thay đổi cục bộ. Tôi thực sự hiểu cảm giác tồi tệ, trang người đàn ông có thể nói "Cập nhật các tệp chưa sửa đổi trong cây làm việc". Mặt khác, Git không dễ làm mất các thay đổi cục bộ. git checkouthoặc để thay đổi cục bộ của bạn một mình, hoặc từ chối nếu có xung đột.
Gauthier

1
tốt, làm thế nào tôi có thể thanh toán đến một chi nhánh khác mà không mang những thay đổi cục bộ đến đó?
ア レ ッ ク

5
@Alex git checkout <other_branch> -f. Bạn sẽ mất những thay đổi cục bộ của bạn mà không có cảnh báo.
Gauthier

2
@ Evi1M4chine Cái đầu tiên. Các tài liệu thực sự xấu.
Qwertie

62

Thử:

git stash
git checkout -b new-branch
git stash apply

6
Điều này có khác với việc chỉ thực hiện 'kiểm tra git -b chi nhánh mới' không?
Adrian Mouat

Tôi không nghĩ đó là khi câu trả lời ban đầu được viết, nhưng tôi có thể sai. Thật không may do hoàn cảnh làm việc của tôi, tôi đã sử dụng lực lượng trong vài năm qua vì vậy tôi không thể chứng thực tính chính xác của nó bây giờ.
Grant Limberg

6
Hoặc thay vì hai bước cuối cùng: git stash chi nhánh mới
hãy thử lại vào

1
git stash không còn cần thiết
kory

Khi bạn có một chi nhánh đã tồn tại nơi bạn muốn đặt tất cả nội dung của mình, stash có ý nghĩa đối với tôi: (Cuối cùng git fetch --all; để lấy chi nhánh từ xa về nguồn gốc) git stash; kiểm tra git <chi nhánh hiện có>; git stash áp dụng;
Paolof76

24

Hai điều bạn có thể làm:

git checkout -b sillyname
git commit -am "silly message"
git checkout - 

hoặc là

git stash -u
git branch sillyname stash@{0}

( git checkout -<- dấu gạch ngang là lối tắt cho nhánh trước bạn đã bật)

( git stash -u<- -ucó nghĩa là nó cũng có những thay đổi chưa được thực hiện)


7

Nếu bạn đang sử dụng ứng dụng khách GitHub Windows (như tôi) và bạn đang ở trong tình huống phải thực hiện các thay đổi không được cam kết mà bạn muốn chuyển sang một chi nhánh mới, bạn có thể chỉ cần "Đóng một chi nhánh mới" thông qua ứng dụng khách GitHub. Nó sẽ chuyển sang nhánh mới được tạo và bảo toàn các thay đổi của bạn.

nhập mô tả hình ảnh ở đây


ngăn chặn các thay đổi trước khi tạo chi nhánh mới để nó không giữ chúng (phiên bản 223 trên Mac OS)
Fernando Gallego

2

Nếu bạn muốn các thay đổi không được cam kết hiện tại của mình trên nhánh hiện tại chuyển sang một nhánh mới, hãy sử dụng lệnh sau để tạo một nhánh mới và tự động sao chép các thay đổi không được cam kết.

git checkout -b branch_name

Điều này sẽ tạo một nhánh mới từ nhánh hiện tại của bạn (giả sử nó là chủ), sao chép các thay đổi không được cam kết và chuyển sang nhánh mới.

Cam kết thay đổi của bạn cho chi nhánh mới.

git commit -m "First commit"

Vì, một nhánh mới được tạo, trước khi đẩy nó vào điều khiển từ xa, bạn cần đặt ngược dòng. Sử dụng lệnh dưới đây để đặt ngược dòng và đẩy nó vào điều khiển từ xa.

git push --set-upstream origin feature/feature/NEWBRANCH

Khi bạn nhấn lệnh này, một nhánh mới sẽ được tạo ở điều khiển từ xa và nhánh cục bộ mới của bạn sẽ được đẩy sang điều khiển từ xa.

Bây giờ, nếu bạn muốn loại bỏ các thay đổi không được cam kết của mình khỏi nhánh chính, hãy sử dụng:

git checkout master -f

Điều này sẽ loại bỏ mọi thay đổi cục bộ không được cam kết khi thanh toán.


Làm thế nào để câu trả lời này khác với câu trả lời được chấp nhận?
kometen

Mặc dù có một số trùng lặp với câu trả lời được chấp nhận, nhưng điều này cung cấp một hướng dẫn từng bước đơn giản và cũng bao gồm các hoạt động cần thiết để đẩy một chi nhánh mới từ xa. Đơn giản, rõ ràng và hữu ích.
Kjartan

Câu trả lời này là rõ ràng và giúp tôi rất nhiều.
Vadim

0

Trong ứng dụng khách GitHub mới nhất cho Windows , nếu bạn có các thay đổi không được cam kết và chọn tạo một nhánh mới.
Nó nhắc bạn cách xử lý tình huống chính xác này:

nhập mô tả hình ảnh ở đây

Điều tương tự cũng áp dụng nếu bạn đơn giản chuyển đổi chi nhánh quá.

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.