242

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

または私のオプションです:

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

12 に答える 12

78

注:この回答を、ベルトの下にさらに24時間git-fuを追加して書き直しました:)私のシェルの歴史では、シバン全体が3つのワンライナーになりました。しかし、私はあなたの便宜のためにそれらを凝縮していません。

このように、盲目的にコピー/貼り付けするのではなく、私がどのように物事を行ったかをご覧いただければ幸いです。


これがステップバイステップです。

スタッシュを含む〜/OLDREPOのソースであると想定します。隠し場所を含まない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
于 2011-03-09T16:22:58.163 に答える
71

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

とにかく混乱するだけです。なぜなら、それはすべての隠し場所をフェッチするのではなく、最新のものだけをフェッチするからです。隠し場所のリストは、refのreflogrefs/stashesです。

于 2009-10-11T10:47:03.120 に答える
32

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

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

  • [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

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

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

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

ただしgit reset --hard HEAD^、コミットはガベージであるため、「[non-commit]」を作成したリポジトリに移動する必要があります。

于 2010-03-29T00:13:25.520 に答える
27

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

私にとってうまくいくのは、進行中のコードをコミットすることです(私が単独で作業しているブランチで)。他のコンピューターにアクセスしたら、プルを実行してから、次のコマンドでコミットを元に戻します。

git reset --soft HEAD^

進行中のすべての変更がコミットされておらず、ステージングされていない状態で、そのまま作業を続けます。

それが役に立てば幸い。

于 2013-08-28T01:13:18.103 に答える
22

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

これについてもここで説明しました。

于 2016-11-07T15:34:51.690 に答える
12

現在受け入れられている答えは技術的に正しいものです。Gitにすべてのスタッシュをリモートにプッシュしてから、すべてを別のコンピューターのローカルスタッシュにプルするように直接指示することはできません。

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

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

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

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

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

rev-parseコマンドは、リポジトリに固有のスタッシュの短いハッシュを取得します。)

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

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

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

create
stash(通常のコミットオブジェクト)を作成し、ref名前空間のどこにも保存せずにそのオブジェクト名を返します。これは、スクリプトに役立つことを目的としています。おそらく、使用したいコマンドではありません。上記の「保存」を参照してください。

store
git stash create(ぶら下がっているマージコミット)を介して作成された特定のstashをstash refに保存し、stashreflogを更新します。これは、スクリプトに役立つことを目的としています。おそらく、使用したいコマンドではありません。上記の「保存」を参照してください。

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

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

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

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

隠し場所は、私のローカルリポジトリに通常どおり表示されます。

$ 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ここで見つけることができます。

于 2020-04-22T02:29:57.430 に答える
9

マスター/フィーチャードブランチにコミットできない理由はわかりませんが、2番目のアプローチを使用します。さくらんぼ狩りも可能です。

于 2009-10-11T10:39:21.967 に答える
6

隠し場所の全体的な考え方は、地元のカーペットの下にそれほど重要ではないものを隠すことです。誰もあなたのお気に入りのがらくたについて知る必要はありません;-)唯一の「しかし」は:しかし、私がいくつかのワークステーションで開発した場合はどうでしょうか?その後scp、はるかに優れています。

于 2011-09-22T07:21:21.387 に答える
1

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

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_
于 2014-07-28T14:10:41.180 に答える
1

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

マシン1:

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

マシン2:

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 branch when not needed from local
git push -d origin stash-branch // Delete branch when not needed from remote
于 2020-03-01T11:39:10.060 に答える
0

他の回答に基づいて、GitHubなどのプラットフォームにパブリックリポジトリがあり、進行中の変更をパブリックにしたくない場合は、プライベートリポジトリを作成してリモートとして追加できます。

変更を同期するには:コミットし、プライベートリモートのブランチにプッシュし、ターゲットデバイスをプルして、ソフト/混合リセットを実行します。

于 2021-05-25T23:23:04.157 に答える
0

zshシェルでどのように行うかを共有するために、上記の2つの回答を組み合わせます。

この質問に答えてくれた@ScottWeldon (answer-link)と@sehe (answer-link)に大いに感謝します!彼らからたくさんのことを学びました!また、この問題のおかげで、シェルスクリプトについて幅広く学びました。


コードが何をするかについての非常に簡単な説明

より良い(推奨される)理解のために上記の回答リンクを参照してください。

コードの機能:

Stash goes from Machine 1 --> to remote --> to Machine 2

マシン1のステップ:

1. Push the stash to remote (using for loop for multiple stashes)

マシン2の手順:

1. Check stash(es) in remote. (This is just to check whether there are  previous stashes in remote. If there are, you must delete them if you don't want them in you stash list. Command for deleting remote stashes are given in bonus)
2. Fetch the stash(es) to a local ref folder named "ref/stashes" in your .git folder in your local repository. (Its like downloading the stashes on your PC)
3. Convert the fetched stash(es) to proper data. (Its like extracting or installing the stashes on your PC)

ボーナス:

1. Check stash(es) in remote
2. Delete stash(es) from remote 

コード:

マシン1:

1. git push origin $(for sha in $(git rev-list -g stash); do echo $sha:"refs/stashes/$(git rev-parse --short $sha)"; done)

マシン2:

1. git ls-remote
2. git fetch origin "refs/stashes/*":"refs/stashes/*"
3. for sha in $(git rev-list --no-walk --reverse --glob='refs/stashes/*'); do git stash store --message "$(git show --no-patch --format=format:%s $sha)" $sha; done

ボーナス:

1. git ls-remote
2. git push origin :refs/stashes/<stashFile-1> :refs/stashes/<stashFile-2>

上記のコードは複数の隠し場所用であり、1つの隠し場所にも使用できます。リモートref/stashesフォルダに、ローカルリポジトリに必要なスタッシュのみが含まれていることを確認してください。

于 2021-11-01T01:14:25.123 に答える