2011-03-12 73 views
40

我剛剛使用「混帳添加-p」添加一堆更改指標,我才意識到,我錯過了一個變化應該已經走了到上一次提交。你如何讓git存儲索引?

我現在不能承諾--amend因爲我已經添加了所有索引這些新的變化,我不想用「git的復位」從索引中刪除所有這些,因爲它會採取年齡將它們全部重新添加。

我需要的是像「git的藏匿」,將只藏指數 - 它應該獨自離開了工作文件。然後,我可以隱藏索引,添加缺失的變化,將其提交,然後彈出存儲並使索引恢復原樣。

它看起來並不像「git的藏匿處」是能夠做到這一點,但我失去的東西嗎?謝謝!

+1

我認爲這只是'git的承諾'你想要 - 它需要你的索引並從它創建一個提交。 Kevin Ballard的答案解釋瞭如何在完成後明智地重寫歷史記錄...... – 2011-03-12 09:34:43

+5

聽起來你想要類似於'git stash --keep-index'的東西,但是對於工作樹。即' - 工作樹'。我也是,它不存在。 – 2012-08-13 19:44:23

+5

爲什麼不作弊? git stash --keep-index將當前不在索引中的所有內容都刪除。現在,git存儲只是上演的東西。混帳隱藏彈出第一個藏匿處,添加您的更改,提交。現在,git reset --hard清理工作樹,然後git存儲pop --index以重新獲得索引更改。 – doliver 2015-01-20 15:07:45

回答

18

最簡單的方法是立即停止該更改,創建新的提交,然後創建第二個提交,只需要修改該更改並使用git rebase -i將其與原始HEAD進行壓縮即可。

另一種方法是讓您的提交,標記它,回滾git reset HEAD^,添加一個更改並修改HEAD,然後櫻桃挑選標記的提交。

+0

完美,我沒有意識到git -i,它完美地製作了這個技巧。謝謝! – Malvineous 2011-03-12 09:40:38

+1

如果你使用的是相對較新版本的git,那麼還要看「autosquash」和「git commit --fixup」選項。 – MatrixFrog 2011-03-12 21:11:10

+0

應該注意的是,你必須指出你想要從哪個提交中提取出來:'git rebase -i HEAD〜2'在這種情況下。 – Auron 2012-02-03 17:02:24

26

我發現的最接近的是git stash --patch。它會引導您完成對工作樹和索引的每個更改,讓您選擇要存儲的內容。

http://www.kernel.org/pub/software/scm/git/docs/git-stash.html

+1

這在合併衝突中不適用於我。我得到了一堆「需要合併」的文件,然後: 致命︰git-write-tree:錯誤構建樹 無法保存當前索引狀態 – theazureshadow 2012-08-20 21:23:00

+0

謝謝這真棒,我認爲隱藏只能保存所有文件,這就是對我的工作流程有很大的改進 – nickel715 2013-09-11 08:03:48

9

提交您的索引,創建一個修正提交,並使用autosquash變基:

git commit 
git add -p       # add the change forgotten from HEAD^ 
git commit --fixup HEAD^   # commits with "fixup! <commit message of HEAD^>" 
git rebase --autosquash -i HEAD~3 
+0

感謝您的建議,但是如果仔細觀察,這就是接受的答案已經推薦的內容:-) – Malvineous 2013-03-03 10:13:49

0

這裏有一個小劇本我已經在過去拿出來做到這一點:

(注:我最初發布這個在https://stackoverflow.com/a/17137669/531021,但它似乎把這裏以及這些不完全重複的問題,所以我認爲它作爲在這兩種情況下可能的答案。)

#!/bin/sh 

# first, go to the root of the git repo 
cd `git rev-parse --show-toplevel` 

# create a commit with only the stuff in staging 
INDEXTREE=`git write-tree` 
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD` 

# create a child commit with the changes in the working tree 
git add -A 
WORKINGTREE=`git write-tree` 
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT` 

# get back to a clean state with no changes, staged or otherwise 
git reset -q --hard 

# Cherry-pick the index changes back to the index, and stash. 
# This cherry-pick is guaranteed to suceed 
git cherry-pick -n $INDEXCOMMIT 
git stash 

# Now cherry-pick the working tree changes. This cherry-pick may fail 
# due to conflicts 
git cherry-pick -n $WORKINGCOMMIT 

CONFLICTS=`git ls-files -u` 
if test -z "$CONFLICTS"; then 
    # If there are no conflicts, it's safe to reset, so that 
    # any previously unstaged changes remain unstaged 
    # 
    # However, if there are conflicts, then we don't want to reset the files 
    # and lose the merge/conflict info. 
    git reset -q 
fi 

您可以將上面的腳本保存爲git-stash-index你的路徑上的某個地方,然後就可以調用它的混帳藏匿指數

# <hack hack hack> 
git add <files that you want to stash> 
git stash-index 

現在藏匿包含一個新的條目,只包含你有變化分階段進行,並且您的工作樹仍然包含任何未分離的更改。

主要的疑難雜症是,你可能無法徹底移除該索引的改變,而不會造成衝突,例如如果工作樹包含取決於索引更改的更改。

在這種情況下,任何這樣的衝突將會留在通常的未合併衝突狀態,類似於一個摘櫻桃/合併之後。

例如

git init 
echo blah >> "blah" 
git add -A 
git commit -m "blah" 

echo "another blah" >> blah 
git add -A 
echo "yet another blah" >> blah 

# now HEAD contains "blah", the index contains "blah\nanother blah" 
# and the working tree contains "blah\nanother blah\nyetanother blah" 

git stash-index 

# A new stash is created containing "blah\nanother blah", and we are 
# left with a merge conflict, which can be resolved to produce 
# "blah\nyet another blah" 
2

我不得不這樣做,並最終使用了一些用於腳本編寫的git存儲選項。 Git存儲創建讓我們創建(但不應用)存儲對象(其中包括索引)。 Git的藏匿處專賣店將其添加到git的藏匿堆棧沒有做git的復位 - 硬了Git藏匿保存隱含一樣。這,有效,讓您的藏匿索引通過增加一個存儲對象的堆棧和手動復位索引:

# This will add an entry to your git stash stack, but *not* modify anything 
git stash store -m "Stashed index" $(git stash create) 

# This will reset the index, without touching the workspace. 
git reset --mixed 

你現在,有效,藏你的指數,可以做一個git藏匿流行--index當你完成。

一個需要注意的是,即使您只關注索引,創建的存儲對象也包括在工作區和索引中更改的文件,因此當您嘗試從堆棧中彈出時甚至可能發生衝突儘管你使用了--index標誌(這意味着「也適用於隱藏索引」,而不是「只應用隱藏索引」)。在這種情況下,您可以在彈出之前執行「git reset --hard」(因爲您重置的更改發生的次數也與您彈出或應用後立即執行的更改相同,所以不會像它似乎。)

5

這似乎工作。我還沒有在所有的情況下進行了測試,以確保它的強大:

git commit -m _stash && git stash && git reset HEAD^ && git stash save && git stash pop [email protected]{1} 

但是,它有效地暫時提交該指數,儲物箱的工作目錄,恢復的承諾得到了指數後面,將其保存爲另一個藏匿,然後從存儲器中再次恢復原始工作目錄。

[alias] 
    istash = "!f() { git commit -m _stash && git stash && git reset HEAD^ && git stash save $1 && git stash pop [email protected]{1}; }; f" 

這讓我使用它像:

git istash [optional stash name] 
6

解決方案1:

爲什麼不騙

這是通過把這個作爲一個git的別名簡化?

git stash --keep-index 

將所有不在索引中的東西都拿出來。 然後,

git stash 

得到一個藏匿與只是真實上演的東西。

git stash pop 

第一個存儲,添加您的更改。然後,

git commit --amend ... 
git reset --hard 

清理工作樹,然後

git stash pop --index 

讓你指數的變化回來。

7

git stash不實際創建與索引的內容提交,然後將所有的內容提交跟蹤在它上面的文件

要查看此:創建一個存儲,然後運行

git log --oneline --graph [email protected]{0} 

因此從技術上講,當你藏起來,你可以通過[email protected]{0}^2拿回你指數:

$ git show --name-only [email protected]{0}^2 
$ git checkout [email protected]{0}^2 -- . 

您還可以藏匿,然後得到在跟蹤的但不添加文件的內容:

# get the diff between what was indexed and the full stashed content : 
$ git diff -p [email protected]{0}^2 [email protected]{0} > diff.patch 
# apply this diff : 
$ git apply diff.patch 
+2

您還可以使用'git stash apply --index'取回索引,然後可以選擇丟棄所有內容其他與'git結帳.' – 2017-04-19 11:25:46

4

magit爲Emacs允許您使用以下命令magit-藏匿指數做到這一點

2
git stash -k 
git stash 
git stash apply [email protected]{1} 
git stash drop [email protected]{1} 
+0

歡迎來到堆棧溢出!儘管這段代碼可以解決這個問題,但[包括一個解釋](// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)確實有助於提高您的帖子的質量。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。也請儘量不要使用解釋性註釋來擠佔代碼,因爲這會降低代碼和解釋的可讀性! – FrankerZ 2017-12-05 19:54:23