Chuyển công việc hiện có, không cam kết sang một chi nhánh mới trong Git


3125

Tôi đã bắt đầu một số công việc trên một tính năng mới và sau khi mã hóa một chút, tôi quyết định tính năng này sẽ nằm trên nhánh riêng của nó.

Làm cách nào để di chuyển các thay đổi không được cam kết hiện có sang một nhánh mới và đặt lại thay đổi hiện tại của tôi?

Tôi muốn đặt lại chi nhánh hiện tại của mình trong khi duy trì công việc hiện có trên tính năng mới.


Chủ đề thú vị tương tự stackoverflow.com/q/556923/269514 ?
Gilberto

Câu trả lời:


3642

Sử dụng như sau:

git checkout -b <new-branch>

Điều này sẽ rời khỏi chi nhánh hiện tại của bạn, tạo và kiểm tra một chi nhánh mới và giữ tất cả các thay đổi của bạn. Sau đó, bạn có thể thay đổi giai đoạn trong các tệp để cam kết với:

git add <files>

và cam kết với chi nhánh mới của bạn với:

git commit -m "<Brief description of this commit>"

Những thay đổi trong thư mục làm việc và những thay đổi được dàn dựng trong chỉ mục chưa thuộc về bất kỳ chi nhánh nào. Điều này thay đổi chi nhánh nơi những sửa đổi sẽ kết thúc.

Bạn không thiết lập lại chi nhánh ban đầu của mình, nó vẫn như cũ. Cam kết cuối cùng <old-branch>vẫn sẽ giống nhau. Do đó bạn checkout -bvà sau đó cam kết.


Cập nhật 2020 / Git 2.23

Git 2.23 bổ sung tiểu ban mới switchtrong nỗ lực xóa một số nhầm lẫn xuất phát từ việc sử dụng quá tải checkout(chuyển nhánh, khôi phục tệp, tách ra, v.v.)

Bắt đầu với phiên bản Git này, thay thế lệnh trên bằng:

git switch -c <new-branch>

Các hành vi là giống hệt nhau và vẫn không thay đổi.


15
Để đảm bảo, tôi cần phải cam kết tính năng chưa hoàn thành TRƯỚC KHI tôi đặt lại chi nhánh ban đầu của mình? Hoặc những tệp không được cam kết sẽ được bảo tồn bất kể cam kết?
Dane O'Connor

192
FYI: những thay đổi trong thư mục làm việc và những thay đổi được dàn dựng trong chỉ mục không thuộc về một chi nhánh. git checkout -b <new branch>những thay đổi trong đó những thay đổi sẽ kết thúc.
Jakub Narębski

152
Nếu bạn đã có một chi nhánh và muốn chuyển các thay đổi của mình sang chi nhánh hiện tại, hãy kiểm tra stackoverflow.com/questions/556923/iêu
Chirantan

14
Nếu bạn muốn đẩy chi nhánh mới của mình vào kho lưu trữ từ xa: stackoverflow.com/questions/2765421/iêu
Dewayne

10
@JDSmith: những thay đổi không phổ biến KHÔNG thuộc về bất kỳ chi nhánh nào. Họ chỉ cư trú trong thư mục làm việc git checkout ./ git reset --hardsẽ loại bỏ chúng một cách không thể phục hồi
knittl

329

Cách khác:

  1. Lưu các thay đổi hiện tại vào ngăn tạm thời:

    $ git stash

  2. Tạo một nhánh mới dựa trên stash này và chuyển sang nhánh mới:

    $ git stash branch <new-branch> stash@{0}

Mẹo: sử dụng phím tab để giảm nhập tên stash.


51
Nếu chi nhánh khác đã tồn tại, bạn có thể chuyển sang chi nhánh đó bằng thanh toán git stash apply.
Archonic

6
Tôi không hiểu mẹo "Mẹo: sử dụng phím tab để giảm nhập tên stash." Không phải là "stash @ {0}" tên sao? Tôi không thể chạy nó thành công.
Herbert

7
Tại sao điều này tốt hơn câu trả lời được chấp nhận stackoverflow.com/a/1394804/754997 ?
Chris Trang

10
Tôi không hiểu tại sao điều này tốt hơn thì câu trả lời được chấp nhận củagit checkout -b <new branch name>
Noitidart

6
Bạn không cần phải git add -Atrước khi đâm.
vichle

48

Nếu bạn đã thực hiện các cam kết trên nhánh chính của mình trong khi bạn mã hóa, nhưng bây giờ bạn muốn chuyển các cam kết đó sang một nhánh khác, đây là một cách nhanh chóng:

  1. Sao chép lịch sử hiện tại của bạn vào một chi nhánh mới, cũng mang theo bất kỳ thay đổi không được cam kết nào:

    git checkout -b <new-feature-branch>
    
  2. Bây giờ, buộc nhánh "lộn xộn" ban đầu quay trở lại: (không chuyển sang nó)

    git branch -f <previous-branch> <earlier-commit-id>
    

    Ví dụ:

    git branch -f master origin/master
    

    hoặc nếu bạn đã thực hiện 4 lần cam kết:

    git branch -f master HEAD~4
    

Cảnh báo: git branch -f master origin/master sẽ đặt lại thông tin theo dõi cho chi nhánh đó. Vì vậy, nếu bạn đã cấu hìnhmasterchi nhánhcủa mìnhđể đẩy đến một nơi khác ngoàiorigin/masterthì cấu hình đó sẽ bị mất.

Cảnh báo: Cũng có một mối nguy hiểm nếu bạn nổi loạn sau khi phân nhánh, được mô tả ở đây . Cách duy nhất để tránh điều đó là tạo ra một lịch sử mới bằng cách sử dụng cherry-pick. Liên kết đó mô tả phương pháp đánh lừa an toàn nhất . Nếu bạn có những thay đổi không được cam kết, bạn có thể muốngit stashbắt đầu vàgit stash popkết thúc.


6
Điều này trả lời một câu hỏi hơi khác với những gì op hỏi. Tôi quyết định đặt câu trả lời này ở đây vì đây là nơi Google mang đến cho tôi khi tôi đang tìm kiếm câu trả lời. Câu hỏi thực tế liên quan đến tình huống này là ở đây .
joeytwiddle

26

Kịch bản phổ biến là như sau: Tôi quên tạo nhánh mới cho tính năng mới và đang thực hiện tất cả công việc trong nhánh tính năng cũ. Tôi đã cam kết tất cả các công việc "cũ" cho chi nhánh chính và tôi muốn chi nhánh mới của mình phát triển từ "chủ". Tôi chưa thực hiện một cam kết nào về công việc mới của mình. Đây là cấu trúc nhánh: "master" -> "Old_feature"

git stash 
git checkout master
git checkout -b "New_branch"
git stash apply

18

Nếu bạn cam kết, bạn cũng có thể chọn ID cam kết duy nhất. Tôi làm điều này thường xuyên khi tôi bắt đầu làm việc trong chủ, và sau đó muốn tạo một chi nhánh địa phương trước khi tôi đẩy lên nguồn gốc của mình /.

git cherry-pick <commitID>

Có rất nhiều thứ bạn có thể làm với cherry-pick, như được mô tả ở đây , nhưng đây có thể là trường hợp sử dụng cho bạn.


2
Giải pháp Nicer để chuyển các thay đổi một phần sang một chi nhánh mới ... vì bạn có thể cam kết những gì bạn muốn bây giờ, bỏ qua tất cả các thay đổi khác, kiểm tra chi nhánh bạn muốn phân nhánh, chọn cherry mà cam kết vào chi nhánh mới, quay lại đến nhánh ban đầu, cứng lại thiết lập lại một cam kết, sau đó thực hiện một stash pop, thêm, cam kết và hát hallelujah.
Meredith

1
@Meredith, haha, ya một cái gì đó như thế. Điều này thật tuyệt, trừ khi bạn lên kế hoạch cho những thay đổi của mình trước ... và ai thực hiện điều đó;)
mật khẩu

1

Điều này có thể hữu ích cho tất cả các công cụ sử dụng cho GIT

Chỉ huy

Chuyển nhánh - nó sẽ chuyển các thay đổi của bạn sang nhánh mới. Sau đó, bạn có thể cam kết thay đổi.

 $ git checkout -b <new-branch>

Rùa

Nhấp chuột phải vào kho lưu trữ của bạn và sau đó sử dụng TortoiseGit-> Switch / Checkout

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

NguồnTree

Sử dụng nút "Thanh toán" để chuyển chi nhánh. Bạn sẽ thấy nút "thanh toán" ở trên cùng sau khi nhấp vào một chi nhánh. Thay đổi từ chi nhánh hiện tại sẽ được áp dụng tự động. Sau đó, bạn có thể cam kết chúng.

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


0

Tôi đã sử dụng @Robin trả lời và liệt kê tất cả những gì tôi đã làm,

git status                               <-- review/list uncommitted changes
git stash                                <-- stash uncommitted changes
git stash branch <new-branch> stash@{1}  <-- create a branch from stash
git add .                                <-- add local changes
git status                               <-- review the status; ready to commit
git commit -m "local changes ..."        <-- commit the changes
git branch --list                        <-- see list of branches incl the one created above
git status                               <-- nothing to commit, working tree (new-branch) is clean
git checkout <old-branch>                <-- switch back

! Nếu repo có nhiều hơn một stash, hãy xem cái nào sẽ áp dụng cho nhánh mới:

git stash list  
  stash@{0}: WIP on ...  
  stash@{1}: WIP on ...

và kiểm tra stash cá nhân bằng cách,

git stash show stash@{1}

Hoặc kiểm tra tất cả các stash cùng một lúc:

git stash list -p

0

Thực sự có một cách thực sự dễ dàng để làm điều này với GitHub Desktop mà tôi không tin là một tính năng trước đây.

Tất cả những gì bạn cần làm là chuyển sang chi nhánh mới trong GitHub Desktop và nó sẽ nhắc bạn rời khỏi các thay đổi của bạn trên nhánh hiện tại (sẽ được lưu lại) hoặc mang các thay đổi của bạn đến chi nhánh mới. Chỉ cần chọn tùy chọn thứ hai, để mang lại những thay đổi cho chi nhánh mới. Sau đó bạn có thể cam kết như bình thường.

Máy tính để bàn GitHub

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.