git stashをリモートリポジトリにプッシュすることはできますか?


205

gitでは、スタッシュを作成し、スタッシュをリモートリポジトリにプッシュし、別のコンピューターでスタッシュを取得して、スタッシュを適用することはできますか?

または私の選択肢は:

  • パッチを作成し、そのパッチを他のコンピューターにコピーする、または
  • マイナーブランチを作成し、不完全な作業をそのブランチにコミットしますか?

回答:


68

fetchなどで取得することはできません。ミラーのrefspecはfetch = +refs/*:refs/*であり、stashであってもrefs/stash送信されません。明示的なrefs/stash:refs/stash効果もありません!

いずれにしても、すべてのスタッシュをフェッチするのではなく、最新のものだけをフェッチするため、混乱を招くだけです。スタッシュのリストはref のreflogですrefs/stashes


4
gitリモートから最新のstashをフェッチできますが、stashにはフェッチできません。別のrefにのみフェッチできます。のようなgit fetch some-remote +refs/stash:refs/remotes/some-remote/stashもの git stash apply some-remote/stash。ただし、古いstashは取得できないreflogに保存されているため、取得できません。stackoverflow.com/questions/2248680/を

75

注:この回答を書き直したところ、私のベルトの下でgit-fuが24時間増えました:)私のシェルの歴史では、シバン全体が3つのワンライナーになっています。ただし、便宜上、それらを解凍しました。

このように、私は物事を盲目的にコピー/貼り付けする必要があるのではなく、私がどのようにしたかを見ることができることを願っています。


ここにステップバイステップです。

スタッシュを含む〜/ OLDREPOのソースであると想定します。stashを含まないTESTクローンを作成します。

cd ~/OLDREPO
git clone . /tmp/TEST

すべてのスタッシュを一時ブランチとしてプッシュします。

git send-pack /tmp/TEST $(for sha in $(git rev-list -g stash); \
    do echo $sha:refs/heads/stash_$sha; done)

受信側でループして、スタッシュに変換し直します。

cd /tmp/TEST/
for a in $(git rev-list --no-walk --glob='refs/heads/stash_*'); 
do 
    git checkout $a && 
    git reset HEAD^ && 
    git stash save "$(git log --format='%s' -1 HEAD@{1})"
done

必要に応じて一時的なブランチをクリーンアップします

git branch -D $(git branch|cut -c3-|grep ^stash_)

git stash listを実行すると、次のようになります。

stash@{0}: On (no branch): On testing: openmp import
stash@{1}: On (no branch): On testing: zfsrc
stash@{2}: On (no branch): WIP on sehe: 7006283 fixed wrong path to binary in debianized init script (reported as part of issue
stash@{3}: On (no branch): WIP on debian-collab: c5c8037 zfs_pool_alert should be installed by default
stash@{4}: On (no branch): WIP on xattrs: 3972694 removed braindead leftover -O0 flag
stash@{5}: On (no branch): WIP on testing: 3972694 removed braindead leftover -O0 flag
stash@{6}: On (no branch): WIP on testing: db9f77e fuse_unmount_all could be starved for the mtx lock
stash@{7}: On (no branch): WIP on xattrs: db9f77e fuse_unmount_all could be starved for the mtx lock
stash@{8}: On (no branch): WIP on testing: 28716d4 fixed implicit declaration of stat64
stash@{9}: On (no branch): WIP on emmanuel: bee6660 avoid unrelated changes

元のリポジトリでは、同じように見えました

stash@{0}: WIP on emmanuel: bee6660 avoid unrelated changes
stash@{1}: WIP on testing: 28716d4 fixed implicit declaration of stat64
stash@{2}: WIP on xattrs: db9f77e fuse_unmount_all could be starved for the mtx lock
stash@{3}: WIP on testing: db9f77e fuse_unmount_all could be starved for the mtx lock
stash@{4}: WIP on testing: 3972694 removed braindead leftover -O0 flag
stash@{5}: WIP on xattrs: 3972694 removed braindead leftover -O0 flag
stash@{6}: WIP on debian-collab: c5c8037 zfs_pool_alert should be installed by default
stash@{7}: WIP on sehe: 7006283 fixed wrong path to binary in debianized init script (reported as part of issue #57)
stash@{8}: On testing: zfsrc
stash@{9}: On testing: openmp import

1
短時間で多くのことを学んでいるので、おそらく以前のアプローチでは、多くのコマンドの使い方を単純にすべきだと思います。
sehe

9
これは私にとってはうまくいきましたが、ステージングされていない限り、新しいファイルを隠しておくことを拒否するためgit add .git stash save ...手順の前に必要でしたgit stash。また、git rev-list ...through の結果をパイプtacすると、スタッシュの順序が逆になり、スタッシュが同じ順序で出てきます。
アランクルーガー

1
@sehe優れたスクリプト!! 2つの提案:1)-隠し場所が元のターゲットリポジトリと同じ順序になるように、最終的な参照リストを逆にします。2)(stashが作成されたらクリーンアップforする)で最終ループを終了します。git branch -D stash_$aこれにより、何か問題が発生して再試行した場合に、既に正常にstashされたコミットを再処理しません。
キース・ロバートソン

1
「解決策を投稿する」のではなく、時間を割いてあなたが何をしたのか説明していただきありがとうございます。
Marjan Venema 16

1
ソリューションをさらに改善することができます:と置き換えるgit stash save "$(git log --format='%s' -1 HEAD@{1})"git update-ref --create-reflog -m "$(git show -s --format=%B $rev)" refs/stash $rev、元の隠しメッセージが表示されます(これupdate-refgit stash save裏で行われています)。
セバスチャンシュレーダー

31

私はパーティーに少し遅れましたが、私はこれに関して私に役立つ何かを見つけたと私は信じています。あなたの状況が同じまたは類似しているなら、それもあなたのためになるかもしれません。

独自のブランチの機能に取り組んでいます。ブランチはマスターにマージされず、終了するまでプッシュされません。または、私が公に見せてもいいと感じるコミットを実行しました。したがって、ステージングされていない変更を別のコンピューターに転送したい場合は、次のようにします。

  • [non-commit] FOR TRANSFER ONLY」のようなコミットメッセージを使用して、転送するコンテンツをフィーチャーしたコミットを作成します。
  • 他のコンピュータにログインします。
  • 次に行います:

    git pull ssh+git://<username>@<domain>/path/to/project/ rb:lb

    別の方法でリポジトリにアクセスすると、URLが異なる場合があります。これにより、そのURLからの変更がリモートブランチ「rb」からローカルブランチ「lb」にプルされます。自分のコンピューターでsshサーバーを実行していて、その方法でリポジトリにアクセスできることに注意してください。

  • git reset HEAD^(意味する--mixed

    これにより、「[非コミット]」コミット前の状態を指すようにHEADがリセットされます。

git-reset(1)から: " --mixed:インデックスをリセットしますが、作業ツリーはリセットしません(つまり、変更されたファイルは保持されますが、コミット用にマークされていません)[...]"

したがって、最終的にファイルへの変更が行われますが、マスターへのコミットは行われず、隠し場所は必要ありません。

ただし、これはgit reset --hard HEAD^「[非コミット]」を作成したリポジトリで行う必要があります。そのコミットは不要であるためです。


そして、これはちょうど....後でそれを削除し、新しい機能ブランチを作成するロット汚いです
Taegost

@Taegostはあなたの環境に依存すると思います。一部のCI / CDの問題で、ブランチを上流に押しやるだけではうまくいかない可能性があります。しかし、はい、好みによっては、ブランチを作成して同じことを実行することもできます。
ビクターザマニアン

22

少し遅いですが、この答えは誰かを助けるかもしれません。進行中の機能/バグ/何でもプッシュして、同じポイントから別のコンピューターで作業できるようにしたかったので、これを知りたいと思いました。

私にとって効果的なのは、進行中のコードをコミットすることです(私が一人で作業しているブランチで)。他のコンピューターにアクセスしたら、プルしてからコミットを元に戻します。

git reset --soft HEAD^

進行中のすべての変更をコミットせず、ステージングせずに、以前と同じように作業を続けます。

それが役に立てば幸い。


これを行おうとすると、Originはまだコミットされていないコミットを維持しています。閉じますが、私にとって葉巻はありません。
rezwits

@rezwitsええ、リモートはそれを保持しますが、一時的なブランチをoriginから削除するだけで十分簡単です。
ロバート卿

実際のところ、それは私がやっていることです!
rezwits 2017

19

これを解決するための非常に巧妙なトリックがあるようです。を使用git diff > file.diff(およびファイルをコミットgit apply file.diff)してから、(どこからでも)を使用して変更を復元し、同じ結果を得ることができます。

これもここで説明さました。


5
追跡されていないファイルがある場合:1. git add。2. git diff HEAD> file.diff
trickpatty

差分を自分にメッセージすることで、リポジトリでのコミットやフットプリントをまったく許可しなくなります!(例:Signalデスクトップアプリを介した自己通知)、または電子メール。
John Mee

9

私は2番目のアプローチを採用しますが、それをmaster / featuredブランチにコミットできない理由はわかりません。チェリーピッキングも可能です。


27
master / featuredにコミットしないという技術的な理由はありません。「これは実際のコミットではなく、単に作業を保存して別のマシンで取得できるようにする」と言いたいだけです。
Andrew Grimm、

4

私の知る限り、隠し場所の全体的なアイデアは、それほど重要ではないものを地元のカーペットの下に隠すことです。誰もあなたの好きながらくたについて知っているべきではありません;-)唯一の "しかし"は次のとおりです。その後scpははるかに優れています。


9
この面白いことはコメントであるべきです。;-)
Andrew Grimm、

2
ここでは合計git-ssh-newbieですが、githubでscpを使用できますか?
公園

いいえ、githubのgit-sshフロントエンドはプログラムされているので、sshシェル/コンソールはありません。サーバー側のgitプロセスのみを実行できます。
argent_smith 2012年

1
したがって、masterブランチがgithubにある場合、scpはこのシナリオでは実際にはオプションではありませんか?その場合、スタッシュを移動するための他の提案はありますか?
公園

1
私は、隠し移動がまったく不可能であることを強調しようとしました、AFAIK。
argent_smith 2012年

2

現在受け入れ答えは、あなたが直接リモートにすべてのあなたのスタッシュをプッシュするのGitに伝え、その後、別のコンピュータ上でローカルのスタッシュにすべてを引くことができない、技術的に正しいです。

そして、 現在トップアップされている回答は機能するはずですが、一時的なブランチの束を作成すること、およびstashコミットを手動でチェックアウトしてstashとして保存する必要があるため、このコメントのような問題につながる可能性があります言及し、重複につながりOn (no branch): On testing:ます。きっともっと良い方法があるに違いない!

したがって、stashを直接プッシュすることはできませんが、stashは単なるコミット(実際には2つのコミット)であり、git pushmanページごとにコミットをプッシュできます。

<src>多くの場合、これはプッシュするブランチの名前ですが、任意の「SHA-1式」にすることができます...

私は隠し場所をプッシュすることにしました refs/stashes/*余分なブランチでリモコンが乱雑にならないように。だから私はそれを行うことができます:

git push origin stash@{0}:refs/stashes/$(git rev-parse --short stash@{0})

rev-parseコマンドはstashの短いハッシュを取得します。これは、リポジトリーに対して一意になります。)

次に、他のコンピューターからスタッシュをフェッチする必要があります。Gitはデフォルトではブランチのみをフェッチするため、具体的にはスタッシュをフェッチする必要があります。

git fetch origin refs/stashes/*:refs/stashes/*

次に、stashコミットを実際のstashに変換します。前述のように、通常どおりstashのコミット、リセット、およびstashをチェックアウトすることはできますが、追加の手順が必要であったり、stashのインデックス状態が維持されない可能性があることは好ましくありません。私はそれを自動的に行う方法をオンラインで探していましたが、私の検索機能に失敗しました。最後に、私はmanページを調べましたgit stashところ、次のことがわかりました。

つくる
(定期的なコミットオブジェクトである)スタッシュを作成し、任意の場所を参照の名前空間に格納することなく、そのオブジェクトの名前を返します。これはスクリプトで役立つことを意図しています。おそらく、使用したいコマンドではありません。上記の「保存」を参照してください。

お店
ストアgitの隠し場所を経て作成された特定のスタッシュがスタッシュREFLOGを更新し、スタッシュREFに(ダングリングマージがコミットされている)を作成します。これはスクリプトで役立つことを意図しています。おそらく、使用したいコマンドではありません。上記の「保存」を参照してください。

私はすでにコミットしているので、store私が望んでいるように聞こえます。だから私はできる:

git stash store --message "$(git show --no-patch --format=format:%s <SHA>)" <SHA>

交換 <SHA>フェッチされたばかりのスタッシュとします。

git showコマンドは、stashコミットからコミットメッセージを取得し、stashログのメッセージとして使用します。)

stashがローカルリポジトリで通常どおり表示されるようになりました。

$ git stash list
stash@{0}: On master: temp
...

リモートをクリーンアップするには、次のようにしてスタッシュをリモートから削除できます。

git push origin :refs/stashes/<SHA>

この方法には、べき等であるという利点もあります。pushコマンドを再度実行すると、が報告されEverything up-to-dateます。fetchまた、このコマンドは安全に繰り返し実行することができます。一方でstash store、それは最も最近のスタッシュと同じである場合、それは古いスタッシュの重複を防ぐことはできませんスタッシュを格納スキップします。ただし、これはgit-rstashスクリプトで行うように回避できます。以下を参照してください。


完了するには、すべてのスタッシュを簡単にプッシュすることもできます( ):

for i in $(seq 0 $(expr $(git rev-list --walk-reflogs --count stash) - 1))
do
  git push origin stash@{$i}:refs/stashes/$(git rev-parse --short stash@{$i})
done

または、フェッチされたすべてのスタッシュをインポートします。

for stash in $(ls .git/refs/stashes)
do
  git stash store --message "$(git show --no-patch --format=format:%s $stash)" $stash
done

私は作成しました サブコマンドとして呼び出すことができるスクリプト(例:)git rstash push 0なので、これをすべて覚える必要はありません。 git-rstashここで見つけることができます。


1

以下はstashでは機能しませんが、作業ディレクトリでのコミットされていない変更では機能しません。ブランチを作成し、現在のすべての変更を自動コミットして、リモートにプッシュします。

commit_and_push_ ( ) {
    # This will:
    #  1. checkout a new branch stash-XXX
    #  2. commit the current changes in that branch
    #  3. push the branch to the remote
    local locbr=${1:-autostash-XXX}
    git checkout -b $locbr
    git add .
    git commit -a -m "Automatically created commit"
    git push origin $locbr
    echo "Autocommitted changes in branch $locbr ..."
}

次のように使用します:

commit_and_push_ my-temp-branch
commit_and_push_

0

新しいstashブランチを作成し、そのブランチが不要な場合は削除するだけです。

git add . // Add work-in-progress job
git checkout -b stash-branch // Create and checkout to stash-branch
git commit -m 'WIP: job description' // Commit message
git push origin stash-branch // Push to remote
git pull origin stash-branch // Pull the stash-branch
git checkout master // Checkout to working branch
git rebase stash-branch // Rebase the stash-branch
git reset --soft // Equivalent to stash!!
git branch -d stash-branch // Delete when not needed from local
git push -d origin stash-branch // Delete when not needed from remote

-9

この人のようにDropboxを使用してください。そうすれば、すべてのコードがバックアップされるため、スタッシュのプッシュについて心配する必要はありません。

http://blog.sapegin.me/all/github-vs-dropbox


2
誰もがすぐに反応する前に、Githubの代わりにDropboxを使用するのではなく、ローカルでバージョン管理されているDropboxでコミットの準備ができていないコードを保存することを言っています。
NYCテクニカルエンジニア

4
すべてのプロジェクトをリモートクラウドにコピーするには時間がかかりすぎます。
Stav Alfi 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.