Câu hỏi Có thể “git pull” tự động stash và bật các thay đổi đang chờ xử lý?


Tôi biết cách giải quyết vấn đề này:

user@host$ git pull
Updating 9386059..6e3ffde
error: Your local changes to the following files would be overwritten by merge:
    foo.bar
Please, commit your changes or stash them before you can merge.
Aborting

Nhưng không có cách nào để git pull làm stash và pop Nhảy cho tôi?

Nếu lệnh này có tên khác thì không sao.

Tạo bí danh vỏ cho git stash; git pull; git stash pop là một giải pháp, nhưng tôi tìm kiếm một giải pháp tốt hơn.


76
2018-05-13 07:58


gốc


những gì về một git bí danh? - Яois
Đang chạy git stash; git pull; git stash pop lập trình là nguy hiểm, bởi vì nếu không có gì để cất giấu, git stash sẽ là no-op, nhưng git stash pop sẽ bật phần cuối cùng (nếu có), gần như chắc chắn không phải bạn muốn gì. Người dùng torek có một bài đăng tuyệt vời về điều này trên Stack Overflow, nhưng tôi không thể tìm thấy nó ... - jubobs
@Jubobs cái này? stackoverflow.com/a/20412685/6309 Hay cái này? stackoverflow.com/a/20480591/6309 - VonC
@ guettli Tôi đã không ngụ ý câu hỏi của bạn là một bản sao, tôi đã chỉ trả lời bình luận của Jubobs. - VonC
Như một bước xa hơn, các hoạt động nên thành công chỉ khi stash có thể được áp dụng sạch sau khi kéo. Nếu có xung đột, thì toàn bộ phép toán không thành công để cây không bị thay đổi. Đây là những gì tôi muốn làm: hoặc kéo xuống những thay đổi với những người địa phương của tôi sáp nhập vào, hoặc người nào khác thất bại với một lỗi và để cho tôi quyết định bằng tay phải làm gì tiếp theo. Đây có phải là loại git 'giao dịch' có thể không? - Ed Avis


Các câu trả lời:


Dành cho Git 2.6+ (phát hành ngày 28 tháng 9 năm 2015)

Duy nhất git config thiết lập mà sẽ được quan tâm là:

rebase.autoStash

Khi được đặt thành true, tự động tạo một dấu mốc tạm thời trước khi bắt đầu hoạt động và áp dụng nó sau khi thao tác kết thúc.
  Điều này có nghĩa rằng bạn có thể chạy rebase trên một worktree bẩn.

Tuy nhiên, sử dụng cẩn thận: ứng dụng stash cuối cùng sau khi rebase thành công có thể dẫn đến xung đột không tầm thường. Mặc định là sai.

kết hợp với:

pull.rebase

Khi đúng, hãy rebase branch trên đầu nhánh đã tìm nạp, thay vì hợp nhất nhánh mặc định từ remote mặc định khi "git pull" được chạy.

git config pull.rebase true
git config rebase.autoStash true

Điều đó sẽ là đủ cho một đơn giản git pull để làm việc ngay cả trong một cây bẩn.
Không có bí danh cần thiết trong trường hợp đó.


Xem cam kết 53c76dc (04/07/2015) bởi Kevin Daudt (Ikke).
(Hợp nhất bởi Junio ​​C Hamano - gitster - - trong cam kết e69b408, Ngày 17 tháng 8 năm 2015) 

pull: cho phép cây bẩn khi rebase.autostash đã bật

rebase đã học được để ngăn chặn những thay đổi khi nó gặp một cây làm việc bẩn thỉu,   nhưng git pull --rebase không làm.

Chỉ xác minh nếu cây làm việc bị bẩn khi rebase.autostash không phải là   đã bật.


Lưu ý: nếu bạn muốn kéo không có autostash (mặc dù rebase.autoStash true được thiết lập), bạn có từ git 2.9 (tháng 6 năm 2016):

 pull --rebase --no-autostash

Xem cam kết 450dd1d, cam kết 1662297, cam kết 44a59ff, cam kết 5c82bcd, cam kết 6ddc97c, cam kết eff960b, cam kết efa195d (02/04/2016) và cam kết f66398e, cam kết c48d73b (21 tháng 3 năm 2016) bởi Mehul Jain (mehul2029).
(Hợp nhất bởi Junio ​​C Hamano - gitster - - trong cam kết 7c137bb, Ngày 13 tháng 4 năm 2016) 

Cam kết f66398e đặc biệt bao gồm:

pull --rebase: thêm vào --[no-]autostash cờ

Nếu rebase.autoStash biến cấu hình được thiết lập, không có cách nào để   ghi đè lên nó cho "git pull --rebase"từ dòng lệnh.

Dạy "git pull --rebase" các --[no-]autostash cờ dòng lệnh   ghi đè giá trị hiện tại của rebase.autoStash, nếu được đặt. Như "git rebase"   hiểu được --[no-]autostash tùy chọn, nó chỉ là vấn đề đi qua   tùy chọn nằm bên dưới "git rebase" khi nào "git pull --rebase" được gọi là.


Cảnh báo: trước Git 2.14 (Q3 2017), "git pull --rebase --autostash"không tự động lưu trữ khi lịch sử cục bộ chuyển tiếp nhanh đến thượng nguồn.

Xem cam kết f15e7cf (01/06/2017) bởi Tyler Brazier (tylerbrazier).
(Hợp nhất bởi Junio ​​C Hamano - gitster - - trong cam kết 35898ea, 05/06/2017) 

pull: ff --rebase --autostash hoạt động trong repo bẩn

Khi nào git pull --rebase --autostash trong một kho chứa bẩn dẫn đến   nhanh về phía trước, không có gì bị tự động và kéo không thành công.
  Điều này là do một phím tắt để tránh chạy rebase khi chúng ta có thể tua đi,   nhưng autostash được bỏ qua trên codepath đó.


Cập nhật: Mariusz Pawelski hỏi trong các bình luận một câu hỏi thú vị:

Vì vậy, mọi người đều viết về autostash khi bạn thực hiện rebase (hoặc pull --rebase).

Nhưng không có ai lấy về việc tự động rửa khi bạn làm việc bình thường với hợp nhất.
  Vì vậy, không có chuyển đổi tự động cho điều đó? Hoặc tôi đang thiếu một cái gì đó? Tôi thích làm git pull --rebase nhưng OP hỏi về "Tiêu chuẩn"git pull

Câu trả lời:

Các chủ đề ban đầu thảo luận về tính năng autostash này, nó đã được thực hiện ban đầu cho cả hai git pull (hợp nhất) và git pull --rebase.

Nhưng ... Junio ​​C Hamano (Git maintainer) lưu ý rằng:

Nếu pull-merge là cái gì đó sẽ gây ra sự "khó chịu"   đã kích hoạt chủ đề này, theo định nghĩa, sự chồng chéo thay đổi cục bộ   với việc hợp nhất và "cửa sổ bật lên" nội bộ này sẽ chạm vào các đường dẫn   hợp nhất được chạm và có thể không dẫn đến "Đã bỏ" nhưng để lại   xung đột hơn nữa để được giải quyết.

tôi nghi ngờ rằng pull.autostash cấu hình không phải là một bổ sung tốt bởi vì nó khuyến khích một công việc xấu, gây đau đớn.
  Trong trường hợp đơn giản, nó có thể không bị tổn thương, nhưng khi những thay đổi cục bộ phức tạp, nó sẽ tích cực làm tổn thương hơn là không có nó, và cấu hình cướp đi sự khích lệ để chọn.

Phương trình này hơi khác với "pull-rebase", là "rebase"   khẳng định bạn bắt đầu từ một cây làm việc sạch sẽ, vì vậy "tải xuống và   sau đó dừng lại "khó chịu cảm thấy lớn hơn. Tôi có một nghi ngờ rằng   nới lỏng mà có thể là một sửa chữa hiệu quả hơn cho vấn đề thực sự.

Vì vậy, liên quan đến việc hợp nhất kéo cổ điển, tốt hơn là:

khuyến khích người dùng suy nghĩ về bản chất của WIP mà anh ta có trong cây đang hoạt động trước khi chạy "git pull".
  Nó là một con thú quá phức tạp có thể can thiệp vào những gì người khác đang làm, hoặc   nó là một sự thay đổi tầm thường mà anh ta có thể cất giấu và bật nó trở lại?

Nếu trước đây, anh ấy sẽ làm tốt hơn nhiều "checkout -b", giữ   làm việc cho đến khi thay đổi cục bộ được đưa vào một hình dạng tốt hơn và   "cam kết", trước khi kéo vào nhánh ban đầu.

Nếu sau này, anh ta sẽ làm tốt hơn:

  • "git pull",
  • sau khi tìm thấy xung đột, chạy      
    • git stash,
    • git merge FETCH_HEAD và
    • git stash pop

111
2018-05-13 08:39



Tính đến 2.4.2, điều này chưa được thực hiện. Có lẽ một ngày nào đó. rebase.autoStash chỉ áp dụng khi sử dụng rebase. pull.rebase chỉ áp dụng khi sử dụng kéo. - Randal Schwartz
"Đó là đủ để một git kéo đơn giản làm việc ngay cả trong một cái cây bẩn thỉu." Như Randal đã bình luận, điều này vẫn chưa đúng. Chủ nhân hiện tại pull.c vẫn chọn die_on_unclean_work_tree. - Pradhan
@Pradhan Tôi đồng ý. Việc thực hiện chỉ có trong chủ buổi sáng này và nên được lên cho git 2,6. Tôi đã chỉnh sửa câu trả lời để làm rõ điều đó. - VonC
Tôi đã xác nhận rằng autostash đang làm việc với git 2.5.5. - Joshua Hoblitt
Vì vậy, mọi người đều viết về autostash khi bạn làm rebase (hoặc là pull --rebase). Nhưng không ai lấy về việc tự động rửa khi bạn làm bình thường pull với sự hợp nhất. Vì vậy, không có chuyển đổi tự động cho điều đó? Hoặc tôi đang thiếu một cái gì đó? Tôi thích làm git pull --rebase nhưng OP hỏi về "tiêu chuẩn" git pull - Mariusz Pawelski


Để tiết kiệm vài giây cho những người khám phá đang tới, dưới đây là tóm tắt (nhờ @VonC):

git pull --rebase --autostash

16
2017-08-12 06:27



Vấn đề là: sau một git config pull.rebase true và git config rebase.autoStash true, tất cả những gì bạn cần là git pull. Chỉ git pull. Không yêu cầu các tùy chọn khác. - VonC
Xuất hiện bạn cần ít nhất Git 2.9 cho --autostash Tùy chọn. Các -c rebase.autoStash=true hoạt động trong Git 2.6 trở đi. - ntc2


Như nhận xét ở trên đã nêu, việc đặt hai giá trị cấu hình hiện không hoạt động với git pull, vì cấu hình autostash chỉ áp dụng cho các lần rebases thực tế. Các lệnh git này làm những gì bạn muốn:

git fetch
git rebase --autostash FETCH_HEAD

Hoặc đặt nó làm bí danh:

git config alias.pullr '!git fetch; git rebase --autostash FETCH_HEAD'

Sau đó làm:

git pullr

Tất nhiên, bí danh này có thể được đổi tên thành mong muốn.


14
2017-07-22 22:56





Với Git 2.6+ bạn có thể sử dụng như sau:

alias gup='git -c rebase.autoStash=true pull --rebase'

Điều này --rebase làm cho việc sử dụng git-pull rebase thay vì merge, do đó, cài đặt / tùy chọn như --ff-only sẽ không áp dụng.

Tôi đang sử dụng bí danh để kéo --ff-only theo mặc định (git pull --ff-only) và sau đó có thể sử dụng gup (từ trên cao) trong trường hợp không thể hợp nhất chuyển tiếp nhanh hoặc có các thay đổi được lưu trữ.


5
2018-04-03 18:18





Như bạn đã đề cập đây là cách để làm điều đó. Bạn có thể sử dụng nó trong bí danh để giúp bạn nhập và sử dụng phím tắt hoặc bạn có thể sử dụng nó trong một dòng (cũng có thể là một bí danh)

git stash && git pull --rebase && git stash pop

Nó sẽ làm điều tương tự như bạn đã làm nhưng trong một dòng (&&) và bạn được đặt làm bí danh, nó thậm chí sẽ ngắn hơn.

Các dòng sau sẽ hiển thị các thay đổi đến / đi trước khi bạn kéo / đẩy

git log ^master origin/master
git log master ^origin/master

1
2018-05-13 08:40



Cách tiếp cận này là không an toàn: nếu không có gì để stash, lệnh đầu tiên sẽ không làm gì cả, và sau đó stash pop sẽ unstash một số công cụ ngẫu nhiên từ trước. - John Zwinck