Cần thiết lập lại nhánh git thành phiên bản gốc


440

Tôi đã vô tình làm việc trên một chi nhánh mà tôi không nên làm trong một thời gian, vì vậy tôi đã tách ra khỏi nó để đặt cho nó cái tên phù hợp. Bây giờ tôi muốn ghi đè lên nhánh mà tôi không nên có trên phiên bản từ nguồn gốc (github). Có cách nào làm dễ hơn không? Tôi đã cố gắng xóa chi nhánh và sau đó thiết lập lại chi nhánh theo dõi, nhưng nó chỉ cung cấp cho tôi phiên bản mà tôi đang làm việc lại.



Với Git 2.23 (tháng 8 năm 2019) : git switch -C mybranch origin/mybranch. Xem câu trả lời được chỉnh sửa của tôi dưới đây
VonC

Câu trả lời:


814

Nếu bạn chưa được đẩy về nguồn gốc, bạn có thể đặt lại chi nhánh của mình thành chi nhánh ngược dòng bằng:

git checkout mybranch
git reset --hard origin/mybranch

(Đảm bảo rằng bạn tham chiếu cam kết mới nhất của mình trong một chi nhánh riêng, như bạn đã đề cập trong câu hỏi của mình)

Lưu ý rằng ngay sau khi thiết lập lại, hãy mybranch@{1}tham khảo cam kết cũ, trước khi đặt lại.

Nhưng nếu bạn đã đẩy, hãy xem " Tạo nhánh git và hoàn nguyên bản gốc về trạng thái ngược dòng " để biết các tùy chọn khác.


Với Git 2.23 (tháng 8 năm 2019) , đó sẽ là một lệnh : git switch.
Cụ thể là:git switch -C mybranch origin/mybranch

Thí dụ

C:\Users\vonc\git\git>git switch -C master origin/master
Reset branch 'master'
Branch 'master' set up to track remote branch 'master' from 'origin'.
Your branch is up to date with 'origin/master'.

Điều đó khôi phục chỉ mục và cây làm việc, giống như git reset --hardsẽ.


Theo nhận xét của Brad Herman , a reset --hardsẽ xóa bất kỳ tệp mới nào hoặc đặt lại tệp đã sửa đổi thành CHÍNH .

Trên thực tế, để chắc chắn bạn bắt đầu từ một "slate sạch", một git clean -f -dsau khi reset sẽ đảm bảo một cây làm việc chính xác giống như các chi nhánh bạn chỉ cần thiết lập lại.


Bài đăng trên blog này gợi ý những bí danh đó (chỉ dành cho masterchi nhánh, nhưng bạn có thể điều chỉnh / mở rộng chúng):

[alias]
   resetorigin = !git fetch origin && git reset --hard origin/master && git clean -f -d
   resetupstream = !git fetch upstream && git reset --hard upstream/master && git clean -f -d

Sau đó, bạn có thể gõ:

git resetupstream

hoặc là

git resetorigin

26
điều này sẽ XÓA các thay đổi UNSTAGED / STAGED (từ --hard)
Peter Ehrlich

5
Tôi đã sử dụng git reset --hard origin/mybranchlệnh nhiều lần khi tôi không quan tâm đến bất kỳ thay đổi cục bộ nào và chỉ muốn một bản sao sạch phù hợp với nguồn gốc. Tuy nhiên, ngày nay, điều này đã không hoạt động - tôi vẫn còn một số tập tin mới, chưa được chỉnh sửa và git tiếp tục hứa với tôi rằng nó đang ở TRƯỚC. Lưu ý về việc git clean -f -dsửa lỗi bằng cách xóa sạch tất cả các tệp mới mà tôi không muốn.
Matthew Clark

@MatthewClark Điều đó được mong đợi: xem bình luận về stackoverflow.com/q/4327708/6309
VonC

1
Tuyệt quá! Cũng nhiều lần tôi đã sử dụng git reset --hard HEADđể trở lại một cam kết trước đó, bỏ qua mọi thay đổi
daronwolff

Điều này có thể với sourctree không?
Lonzak

20

Giả sử đây là những gì đã xảy ra:

# on branch master
vi buggy.py                 # you edit file
git add buggy.py            # stage file
git commit -m "Fix the bug" # commit
vi tests.py                 # edit another file but do not commit yet

Sau đó, bạn nhận ra bạn thay đổi trên nhánh sai.

git checkout -b mybranch    # you create the correct branch and switch to it

Nhưng mastervẫn chỉ vào cam kết của bạn. Bạn muốn nó chỉ ra nơi nó chỉ trước.

Giải pháp

Cách dễ nhất là:

git branch --force master origin/master

Một cách khác là:

git checkout master
git reset --soft origin/master
git checkout mybranch

Lưu ý rằng việc sử dụng reset --hardsẽ khiến các thay đổi không được cam kết của bạn bị mất ( tests.pytrong ví dụ của tôi).


Điều đó có vẻ an toàn hơn trong câu trả lời của tôi;) +1
VonC

8

Tôi có một repo riêng trên máy chủ và thường xuyên rebase / force-đẩy tới nó, điều này khiến cho việc thiết lập lại nhánh cục bộ trên máy tính khác của tôi thường xuyên là cần thiết. Do đó, tôi đã tạo ra bí danh "bắt", cho phép thực hiện điều này cho nhánh hiện tại. Không giống như câu trả lời khác, không có tên nhánh được mã hóa cứng trong bí danh này.

Giữ chặt.

[alias]
  catchup = "!f(){ echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \"; read -r ans; if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)); else echo \"catchup aborted\"; fi }; f"

Được định dạng đúng (sẽ không hoạt động với các dòng mới trong .gitconfig) giống như sau:

"
!f(){
  echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \";
  read -r ans;
  if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then
    git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD));
  else
    echo \"catchup aborted\";
  fi
}; f
"
  • Các \\033[0;33m\\033[0mlà để nhấn mạnh các chi nhánh hiện tại và thượng nguồn với màu sắc.
  • $(git symbolic-ref -q --short HEAD) là tên chi nhánh hiện tại
  • $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)) là thượng nguồn của chi nhánh hiện tại.

Vì đặt lại là một cuộc gọi nguy hiểm tiềm tàng (đặc biệt là với tùy chọn --hard, bạn sẽ mất mọi thay đổi không được cam kết), trước tiên, nó sẽ cho bạn biết những gì nó sẽ làm. Ví dụ: nếu bạn đang ở trên nhánh dev-container có điều khiển từ xa được gọi là qcpp / dev-container và bạn nhập git catchup, bạn sẽ được nhắc:

đặt lại dev-container thành qcpp / dev-container? (Y / n)

Nếu sau đó bạn gõ y hoặc chỉ cần nhấn return, nó sẽ thực hiện thiết lập lại. Nếu bạn nhập bất cứ điều gì khác, việc thiết lập lại sẽ không được thực hiện.

Nếu bạn muốn siêu an toàn và lập trình ngăn chặn mất các thay đổi không được thực hiện / không được cam kết, bạn có thể điều chỉnh các bí danh ở trên bằng cách kiểm tra chỉ số khác .

Từ cảnh báo bắt buộc: Nếu bạn đang làm việc trên một kho lưu trữ công cộng mà người khác đã làm việc dựa trên và bạn cần bí danh này, bạn đã làm sai ™ .


1

Tôi đã thử điều này và nó đã không thiết lập lại chi nhánh hiện tại của tôi thành github từ xa mới nhất của tôi. Tôi googled và tìm thấy https://itsyndicate.org/blog/how-to-use-git-force-pull-properly/

mà đề nghị

git fetch origin master
git reset --hard origin/master

Tôi muốn thiết lập lại chi nhánh v8 của mình vì vậy tôi đã làm

git fetch origin v8
git reset --hard origin/v8

va no đa hoạt động


Vâng, thật tốt khi bạn đề cập đến. Tôi đã làm điều đó một lần mà không có và thiết lập lại mọi thứ về 2 năm trước :)
Adam
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.