web-dev-qa-db-ja.com

--skip-worktreeの後にブランチを切り替えることはできません

私がしたいこと

機密データを含むファイルがあるので、このファイルのコンテンツをリモートサーバーにプッシュしたくありません。

私がしたこと?

これを実現するために、ファイルが空のときにコミットを行い、この空のファイルをサーバー(GitHub)にプッシュしました。次に、ファイルに機密データを入力し、git update-index --skip-worktree path/to/fileを適用します。しかし、私は何のコミットもしませんでした。

今、ブランチを切り替えようとしていますが、このエラーが発生します:

    error: Your local changes to the following files would be overwritten by checkout:
    path/to/file
    Please, commit your changes or stash them before you can switch branches.
    Aborting

skip-worktreeの代わりにassume-unchangedを使用する理由

私はこの主題に関するいくつかのSO質問を読み、 Borealidの答え を見つけました。

--assume-unchangedは、開発者がファイルを変更してはならないことを前提としています。このフラグは、SDKのような変更されないフォルダーのパフォーマンスを向上させることを目的としています。

--skip-worktreeは、開発者が特定のファイルを変更する必要があるため、特定のファイルに触れないようにgitに指示する場合に役立ちます。たとえば、メインリポジトリのアップストリームが本番環境に対応した構成ファイルをホストしていて、それらのファイルに誤って変更をコミットしたくない場合は、-skip-worktreeがまさに必要です。

この後、 ジェフの質問VonCの答え を見つけました。ジェフの問題は私のものとほとんど同じで、私はVonCの解決策に従いました。しかし、それは私にはうまくいきません。おそらくgitバージョンの違いが原因です。その質問は2012年からです。私たちはVonCと話をしましたが、彼は答えを思い出せなかったので、これを新しい質問として尋ねると言いました。

--assume-unchanged--skip-worktreeを一緒に使用して、ワークツリーをソフトリセットしようとしました。しかし、何も変わりませんでした。

そう?

私の問題について教えてもらえますか?

ありがとうございました。

40
Eray

これに対する適切な解決策を見つけることができなかったので、影響を受けるファイルに対して.batファイルを使用して--no-skip-worktreeを実行しています。次に、stash、ブランチstash applyを切り替え、別の.batファイルを使用して同じファイルで--skip-worktreeを実行します。

ニースではありませんが、これまでに見つけた中で最も簡単で迅速な方法です。

更新:この問題が再び発生したため、上記の.batファイルの代わりにPowerShellスクリプトを作成しました。ファイルをスキップするかスキップしないかをユーザーに確認します。 2つのパラメーターを更新すると、準備が整います。

[string]$repoPath = "C:\Fully\Qualified\Path"
[string[]]$filesToSkip = @(
    "Local/Path/To/File.txt",
    "Local/Path/To/OtherFile.txt"
)

$skipText = Read-Host -Prompt 'Skip files? (y/n)'
$skip = $skipText -like "y"
cd $repoPath
foreach ($file in $filesToSkip)
{
    if($skip)
    {
        Write-Host "Skipping" $file
        git update-index --skip-worktree $file
    }
    else
    {
        Write-Host "No-skipping" $file
        git update-index --no-skip-worktree $file
    }
}
8
stevospinks

すべてのファイルで--no-skip-worktreeを実行する1行を見つけるだけです

git ls-files -v | grep "^S" | cut -c 3- | xargs -L1 git update-index --no-skip-worktree

そのコマンドで簡単に小さなalias.unhideallを作成できます:)

1
Mickaël B.

そのファイルの空のバリアントをチェックインする理由はありますか?そうでない場合

git rm --cached path/to/file
echo 'path/to/file' >> .gitignore
git commit -m'stop tracking path/to/file'

あなたの問題を解決するかもしれません。 (ファイルがあるブランチごとに繰り返す必要があります。または、履歴の書き換えを気にしない場合は、git filter-branchを使用して、以前のコミットでもそれを取り除きます。)

1
das-g

スパースチェックアウトを有効にしてそこにファイルを追加する スキップワークツリーフラグを追加するとともに(スパースチェックアウトのみを追加すると、おそらく削除されます)。

ファイルを除外するには、sparse-checkoutファイルに配置する必要があります( git-read-tree manualを参照):

/*
!unwanted

その後、更新時に変更されません(したがって、他のブランチのコンテンツは取得されず、代わりに編集内容が保持されます)。それはあなたが望むものではないかもしれません。

1
max630

まあ、これは厄介な解決策ですが、かなりうまく機能しているようです(テストはわずかですが):

PATHのどこかにgit-checkoutswという名前のファイルを次の内容で作成します。

#!/bin/bash
ignored=( $(git ls-files -v | grep "^S " | cut -c3-) )
for x in "${ignored[@]}"; do
  git update-index --no-skip-worktree -- "$x"
done
git checkout -m $@
for x in "${ignored[@]}"; do
  git update-index --skip-worktree -- "$x"
done

スクリプトは、無視されたファイルのリストをキャプチャし、それらを無視せず、-m(マージ用)およびその他のパラメーターが指定されている新しいブランチをチェックアウトしてから、それらを再度無視します。

これで、git checkoutswの代わりにgit checkoutを実行できます。

1
Raman

これまでのところ、-assume-unchangedと--skip-worktreeは私が見つけたようには機能しません。私のgitバージョンは次のとおりです。gitバージョン2.8.4(Apple Git-73)Stashは、これまでのところ機能する唯一の方法です。

0
user2762938