Làm thế nào tôi có thể đổi tên một git stash?


202

Tôi có một stash với một tên không chính xác. Tôi muốn sửa tên để nó chính xác.

Làm thế nào tôi có thể đổi tên một stash?


5
bật nó và lưu nó một lần nữa với một tên khác?
Bartlomiej Lewandowski

5
Popping và stash một lần nữa không phải là một lựa chọn, bởi vì stash có thể dựa trên trạng thái lỗi thời và dẫn đến xung đột khi bật. (Trạng thái lỗi thời thậm chí không còn tồn tại ở bất kỳ đâu trong lịch sử nữa.)
Tom

Câu trả lời:


258

Giả sử danh sách stash của bạn trông như thế này:

$ git stash list
stash@{0}: WIP on master: Add some very important feature 
stash@{1}: WIP on master: Fix some silly bug

Trước tiên, bạn phải xóa mục nhập stash mà bạn muốn đổi tên:

$ git stash drop stash@{1}
Dropped stash@{1} (af8fdeee49a03d1b4609f294635e7f0d622e03db)

Bây giờ chỉ cần thêm nó một lần nữa với thông báo mới bằng cách sử dụng sha of commit trả lại sau khi thả:

$ git stash store -m "Very descriptive message" af8fdeee49a03d1b4609f294635e7f0d622e03db

Và đó là:

$ git stash list
stash@{0}: Very descriptive message
stash@{1}: WIP on master: Add some very important feature

Giải pháp này yêu cầu git 1.8.4 trở lên, và vâng, nó cũng hoạt động với thư mục làm việc bẩn.


3
git show stash@{0}vẫn hiển thị thông tin cũ sau đó Làm thế nào để khắc phục điều đó? (Xin lưu ý rằng stash sau đó nhận được một SHA khác.)
Tino

4
Cảm thấy tốt hơn để có được băm với git showvà bắt đầu với git stash store. Sau đó, với git stash listbạn sẽ thấy stash cũ và mới. Cuối cùng, bạn có thể dọn sạch rác cũ git stash drop.
hogi

6
git stash thả không mất những thay đổi?
Shravya Boggarapu

4
@ShravyaBoggarapu, không, git không xóa cam kết cho đến khi git gcđược chạy. Sau khi stash dropbạn có thể dễ dàng tìm thấy cam kết không thể truy cập thông thường này bằng cách sử dụng git fsck | grep commitlệnh.
qzb

2
@ ÐerÆndi chỉ cần áp dụng và lưu là một tùy chọn dễ dàng, nhưng không hoạt động khi các thay đổi không thể được áp dụng lại do xung đột. Trong khi đó thả và lưu trữ các công trình trong bất kỳ trường hợp. Tôi đã thử nghiệm giải pháp của mình một lần nữa - nó chỉ hoạt động tốt trên phiên bản git mới nhất (2.17.0).
qzb

62

Trừ khi bạn làm thủ công hoặc đóng góp cải tiến cho Git, bạn có thể sử dụng bí danh:

git config --global alias.stash-rename '!_() { rev=$(git rev-parse $1) && git stash drop $1 || exit 1 ; git diff-index --quiet HEAD; s=$?; [ $s != 0 ] && git stash save "tmp stash from stash-rename"; git stash apply $rev && shift && git stash save "$@" && [ $s != 0 ] && git stash pop stash@{1}; }; _'

Cách sử dụng: " git stash-rename <stash> [save options] [<message>]"

Với [save options]bất kỳ tùy chọn nào của git stash save:[-p|--patch] [-k|--[no-]keep-index] [-q|--quiet] [-u|--include-untracked] [-a|--all]

Thí dụ:

$ git stash list
stash@{0}: On master: Pep8 format
stash@{1}: On master: co other than master with local changes
stash@{2}: On master: tests with deployAtEnd

# Let's say I want to rename the stash@{2} adding an issue reference:
$ git stash-rename stash@{2} NXP-13971-deployAtEnd

$ git stash list
stash@{0}: On master: NXP-13971-deployAtEnd
stash@{1}: On master: Pep8 format
stash@{2}: On master: co other than master with local changes

Điều đó sẽ hoạt động ngay cả khi bạn có những thay đổi cục bộ :)

EDIT 2016/02/22

Tập lệnh được đơn giản hóa, ghi có vào qzb , https://stackoverflow.com/a/35549615/515973

git config --global alias.stash-rename '!_() { rev=$(git rev-parse $1) && git stash drop $1 || exit 1 ; git stash store -m "$2" $rev; }; _'

Cách sử dụng: " git stash-rename <stash> [<message>]"


1
Tuyệt vời! Thậm chí mát hơn nếu bạn có thể làmgit stash-rename 'tests with deployAtEnd' 'NXP-13971-deployAtEnd'
mikemaccana

3
Vì vậy, câu trả lời là 1) bản sao làm việc sạch sẽ, 2) áp dụng stash bạn muốn đổi tên, 3) thả nó từ danh sách stash, 4) tạo một stash mới với thông điệp chính xác.
gcb

2
Để làm rõ, bạn đang đổi tên stash cuối cùng, và sau hành động đó nó trở thành stash hàng đầu?
onebree

2
Tôi xóa stash để đổi tên, lưu các thay đổi hiện tại nếu có, tạo lại stash đã xóa bằng tên mong muốn, áp dụng lại các thay đổi hiện tại nếu có.
Julien Carsique

3
Phiên bản này kiểm tra để đảm bảo cả hai đối số đều ở đó để nó không vô tình làm rơi bản gốc cuối cùng của bạn. Nó cũng chỉ yêu cầu số stash, không phải toàn bộ stash@{0}tài liệu tham khảo. gist.github.com/jdforsythe/f248bf6c72fc020225cc3e315a32e922 git config --global alias.stash-rename '!_() { if [ -z \"$1\" ] || [ -z \"$2\" ]; then echo \"git stash-rename 0 NewName\" && echo \"\" && git stash list && exit 1; else stash=\"stash@{$1}\"; rev=$(git rev-parse \"${stash}\"); git stash drop \"${stash}\" || exit 1; git stash store -m \"$2\" \"$rev\" || exit 1; git stash list; fi }; _'
jdforsythe

6

Nó rất đơn giản. Đầu tiên, hoàn tác stash cuối cùng với:

git stash pop

Sau này, yo có thể lưu stash với một tên tùy chỉnh theo cách này:

git stash save "your explanatory name"

Tôi hy vọng nó hữu ích cho bạn. :)


Stash được đổi tên có thể không phải là gần đây nhất.
mikemaccana

Thumbs up vì điều này đơn giản hơn (CHỈ) cho stash gần đây nhất.
Kaihua

3

Tôi không nghĩ rằng nó có thể làm như vậy. Đã có một đề xuất đổi tên stash, nhưng nó chưa được thực hiện.

Ý tưởng chung của tôi là:

  1. Thực hiện một git reflog updatelệnh mới cập nhật thông báo liên quan đến một mục nhập reflog cụ thể. Để làm điều này, một update_reflog_ent()chức năng mới (trong reflog.c ) sẽ thay đổi thông báo liên quan đến mục nhập reflog cụ thể để cập nhật. Một update_reflog()chức năng sẽ sử dụng for_each_reflog_ent()vớiupdate_reflog_ent để thực sự làm thay đổi.

  2. Một git stash renamelệnh sau đó sẽ chỉ cần gọi git reflog updatevới thông báo thích hợp và thông báo mới.

Hoặc, bạn có thể, tất nhiên, bật stash và làm một git stash save [message]


3

Vì lợi ích của người đọc, đây là phần mở rộng cho câu trả lời hiện được chấp nhận và đúng .

Nếu bạn không chỉ muốn sửa thông báo stash và còn muốn sửa thông điệp cam kết của stash, như vậy

git stash list

git log --oneline -1 stash

cả hai đồng ý với những gì được hiển thị, bạn cần thêm một chút. Có thể có một cách tốt hơn để làm điều đó, nhưng công thức này ở đây rất dễ hiểu, tôi hy vọng.

Để có thể làm được, git commit --amendbạn cần phải ở trên TIP của một chi nhánh. Do đó, giải pháp là:

git checkout -b scratch stash@{1}
git stash drop stash@{1}
git commit --amend -m "$MESSAGE"
git stash store -m "$MESSAGE" HEAD
git checkout master
git branch -D scratch

Giải thích:

  • Tạo một nhánh "cào" mới (chưa tồn tại) từ "stash in question" và chuyển sang nó
  • Loại bỏ stash cũ. Điều này là an toàn, vì chúng tôi vẫn có điều này trên chi nhánh.
  • Sử dụng git commit --amendđể thay thế thông điệp cam kết, điều này thay đổi SHA của "stash in question"
  • Lưu trữ stash, dựa trên câu trả lời của qzb
  • Chuyển về (giả sử bạn đến từ "chính chủ") và dọn dẹp

Hạn chế:

  • Điều này tạm thời chuyển nhánh. Vì vậy, công thức này chỉ có thể được áp dụng khi git status --porcelainsạch (đọc: không xuất bất cứ thứ gì)

  • Nó gia hạn các stash, vì vậy stash đã thay đổi trở thành stash@{0}

  • Bạn cần nhập $MESSAGEhai lần hoặc sử dụng một số biến môi trường (trong ví dụ MESSAGE:)

  • Bạn cần tìm một tên chi nhánh không sử dụng

Có nhiều cách để làm điều này mà không cần chuyển nhánh, nhưng điều này nằm ngoài phạm vi của câu trả lời này.

Thí dụ

git init scratch
cd scratch
for a in A B C D; do date >$a; git add $a; git commit -m $a; done
for a in X Y; do echo $a > Z; git stash save --all; done
git log --oneline --graph --decorate --all; git stash list

Đầu ra

*-.   e0e281b (refs/stash) WIP on master: 8bdcc32 D
|\ \  
| | * 4d62f52 untracked files on master: 8bdcc32 D
| * 096f158 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: WIP on master: 8bdcc32 D
stash@{1}: WIP on master: 8bdcc32 D

Bây giờ không thay đổi cam kết (lưu ý: SHA sau đây sẽ khác ở bên bạn):

git stash drop stash@{1}
git stash store -m ...changed... 2fbf9007dfdfb95ae269a19e13b8b9ca3e24181c
git log --oneline --graph --decorate --all; git stash list

Đầu ra

*-.   2fbf900 (refs/stash) WIP on master: 8bdcc32 D
|\ \  
| | * 246dc5c untracked files on master: 8bdcc32 D
| * 80c5ea0 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: ...changed...
stash@{1}: WIP on master: 8bdcc32 D

Như bạn có thể thấy, stash@{0}vẫn được hiển thị như 2fbf900 (refs/stash) WIP on master: 8bdcc32 Dtronggit log . Nếu bạn nhìn kỹ, bạn sẽ thấy, một số cam kết đã thay đổi SHA. Điều này là do cách xử lý stash (cha mẹ được bao gồm SHA và stash có stash là cha mẹ).

Khắc phục điều đó:

git checkout -b scratch stash
git stash drop
git commit --amend -m ...changed...
git stash store -m ...changed... HEAD
git checkout master
git branch -D scratch
git log --oneline --graph --decorate --all; git stash list

Đầu ra

*-.   4d55186 (refs/stash) ...changed...
|\ \  
| | * 246dc5c untracked files on master: 8bdcc32 D
| * 80c5ea0 index on master: 8bdcc32 D
|/  
* 8bdcc32 (HEAD, master) D
* c84c659 C
* 49bb2da B
* b1852c6 A
stash@{0}: ...changed...
stash@{1}: WIP on master: 8bdcc32 D

Như bạn cũng có thể thấy, refs/stashSHA cũng đã thay đổi.


Đáng nói hơn: điều này sẽ phá hủy chỉ mục đã được lưu với stash ban đầu, thay thế nó bằng một chỉ mục mới phù hợp với cam kết gốc của stash ban đầu. Nếu một người không có kế hoạch sử dụng chỉ mục đã lưu ban đầu (hoặc nó đã khớp với cha mẹ của bản gốc), thì đây không phải là vấn đề.

1

Dưới đây là phiên bản sửa đổi của bí danh của Julien cho phép bạn xử lý chính xác On <branch>tiền tố thường được đặt trước để bỏ tên:

git config --global alias.stash-rename '!_() { newmsg="$1" && stash=${2:-"stash@{0}"} && newbranch="$3" && sha=$(git rev-parse "$stash") && olddesc="$(git stash list --format=%gs -1 "$stash")" && newdesc="$(if [[ "$newbranch" = "." ]]; then echo "$newmsg"; else if [[ -n "$newbranch" ]]; then echo "On $newbranch: $newmsg"; else if [[ "$olddesc" =~ ":" ]]; then echo "$(echo "$olddesc" | cut -f1 -d":"): $newmsg"; else echo "$newmsg"; fi; fi; fi)" && git stash drop "$stash" > /dev/null || exit 1; git stash store -m "$newdesc" "$sha" && git stash list; }; _'

Cú pháp:

git stash-rename <new-name> [<stash> [<new-branch-name> | .]]

Ví dụ sử dụng:

repo[master] % touch tmp && git add tmp && git stash save first
Saved working directory and index state On master: first
HEAD is now at bd62064 Initial commit
repo[master] % touch tmp && git add tmp && git stash save second
Saved working directory and index state On master: second
HEAD is now at bd62064 Initial commit
repo[master] % git stash list
stash@{0}: On master: second
stash@{1}: On master: first
repo[master] % git stash-rename renamed
stash@{0}: On master: renamed
stash@{1}: On master: first
repo[master] % git stash-rename also-renamed stash@{1}
stash@{0}: On master: also-renamed
stash@{1}: On master: renamed
repo[master] % git stash-rename branch-changed stash@{0} new-branch
stash@{0}: On new-branch: branch-changed
stash@{1}: On master: renamed
repo[master] % git stash-rename branch-name-persists
stash@{0}: On new-branch: branch-name-persists
stash@{1}: On master: renamed
repo[master] % git stash-rename no-branch stash@{0} .
stash@{0}: no-branch
stash@{1}: On master: renamed
repo[master] % git stash-rename renamed
stash@{0}: renamed
stash@{1}: On master: renamed
repo[master] % git stash-rename readd-branch stash@{0} develop
stash@{0}: On develop: readd-branch
stash@{1}: On master: renamed

Hầu hết các lệnh là để phân tích cú pháp các đối số và tìm ra những gì nên được thực hiện cho tên nhánh. Các gitcông cụ được sử dụng như sau:

  • git rev-parse <stash> để tìm SHA của stash.
  • git stash list --format=%gs -1 <stash>để tìm chủ đề reflog của stash. Lưu ý rằng điều này khác với thông báo cam kết của stash, không được thay đổi bởi lệnh này. Chủ đề reflog là những gì hiển thị git stash listvà bạn có thể thay đổi chủ đề reflog mà không thay đổi giá trị băm của các cam kết liên quan đến stash. Tuy nhiên, bạn luôn có thể tìm thấy thông điệp cam kết ban đầu, vì vậy đừng sử dụng git stash-renameđể xóa thông tin nhạy cảm!
  • git stash drop <stash>để bỏ tham chiếu cũ vào stash (nhưng chúng ta vẫn có SHA, vì vậy nó không bị mất).
  • git stash store -m <new-message> <sha>để lưu một tham chiếu mới vào stash với cùng thông tin cam kết nhưng một chủ đề reflog khác .
  • git stash listđể liệt kê các stash sau khi hoạt động kết thúc. Lưu ý rằng stash mới luôn được đẩy đến đầu danh sách. Nó sẽ là cần thiết để đẩy lại tất cả các stash trước khi stash quan tâm để khôi phục vị trí ban đầu của nó.

0

Cách đơn giản nhất: bật stash của bạn bằng git stash pop sau đó lưu lại với git stash lưu tên của bạn


Stash được đổi tên có thể không phải là gần đây nhất.
mikemaccana
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.