gitでは、stashを作成し、stashをリモートリポジトリにプッシュし、別のコンピューターでstashを取得して、stashを適用することは可能ですか?
または私のオプションです:
- パッチを作成して他のコンピューターにパッチをコピーする、または
- マイナーブランチを作成し、そのブランチに不完全な作業をコミットしますか?
注:この回答を、ベルトの下にさらに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
フェッチなどで取得することはできません。ミラーrefspecはfetch = +refs/*:refs/*
であり、stashであってもrefs/stash
送信されません。明示的refs/stash:refs/stash
でも効果はありません!
とにかく混乱するだけです。なぜなら、それはすべての隠し場所をフェッチするのではなく、最新のものだけをフェッチするからです。隠し場所のリストは、refのreflogrefs/stashes
です。
私はパーティーに少し遅れていますが、これに関して私に役立つ何かを見つけたと思います。あなたの状況が同じか類似している場合は、あなたにも役立つかもしれません。
私は独自のブランチで機能に取り組んでいます。ブランチはマスターにマージされず、完了するまでプッシュされません。または、一般に公開するのが快適だと感じるコミットを行いました。したがって、ステージングされていない変更を別のコンピューターに転送する場合は、次のようにします。
[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]」を作成したリポジトリに移動する必要があります。
少し遅いですが、この答えは誰かを助けるかもしれません。進行中の機能/バグ/その他をプッシュして、別のコンピューターの同じポイントから作業できるようにしたかったので、これを知りたかったのです。
私にとってうまくいくのは、進行中のコードをコミットすることです(私が単独で作業しているブランチで)。他のコンピューターにアクセスしたら、プルを実行してから、次のコマンドでコミットを元に戻します。
git reset --soft HEAD^
進行中のすべての変更がコミットされておらず、ステージングされていない状態で、そのまま作業を続けます。
それが役に立てば幸い。
これを解決するための非常に巧妙なトリックがあるようです。を使用してgit diff > file.diff
(そしてファイルをコミットして)、(どこからでも)を使用して変更を復元しgit apply file.diff
、同じ結果を得ることができます。
これについてもここで説明しました。
現在受け入れられている答えは技術的に正しいものです。Gitにすべてのスタッシュをリモートにプッシュしてから、すべてを別のコンピューターのローカルスタッシュにプルするように直接指示することはできません。
そして、現在最も賛成されている答えは機能するはずですが、それが一時的なブランチの束を作成すること、そして手動でstash commitをチェックアウトし、それをstashとして保存する必要があることは好きではありませんでした。これは、このコメントのような問題につながる可能性があります言及され、重複につながりOn (no branch): On testing:
ます。確かにもっと良い方法があるはずです!
したがって、スタッシュを直接プッシュすることはできませんが、スタッシュは単なるコミット(実際には2つのコミット)であり、git push
manページごとにコミットをプッシュできます。
多くの場合、これ
<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
スクリプトで行っているように、回避できます。以下を参照してください。
完了するために、すべてのスタッシュを簡単にプッシュすることもできます(bashを使用)。
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
サブコマンド(例)として呼び出すことができるbashスクリプトを作成したgit rstash push 0
ので、これらすべてを覚えておく必要はありません。 git-rstash
ここで見つけることができます。
マスター/フィーチャードブランチにコミットできない理由はわかりませんが、2番目のアプローチを使用します。さくらんぼ狩りも可能です。
隠し場所の全体的な考え方は、地元のカーペットの下にそれほど重要ではないものを隠すことです。誰もあなたのお気に入りのがらくたについて知る必要はありません;-)唯一の「しかし」は:しかし、私がいくつかのワークステーションで開発した場合はどうでしょうか?その後scp
、はるかに優れています。
以下は、スタッシュでは機能しませんが、作業ディレクトリのコミットされていない変更では機能します。ブランチを作成し、現在のすべての変更を自動コミットして、リモートにプッシュします。
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_
新しい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
他の回答に基づいて、GitHubなどのプラットフォームにパブリックリポジトリがあり、進行中の変更をパブリックにしたくない場合は、プライベートリポジトリを作成してリモートとして追加できます。
変更を同期するには:コミットし、プライベートリモートのブランチにプッシュし、ターゲットデバイスをプルして、ソフト/混合リセットを実行します。
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
フォルダに、ローカルリポジトリに必要なスタッシュのみが含まれていることを確認してください。