web-dev-qa-db-ja.com

どうやって "git pull"でローカルファイルを上書きするのですか?

どうやってgit pullのローカルファイルを上書きするのですか?

シナリオは以下のとおりです。

  • チームメンバーが取り組んでいるウェブサイトのテンプレートを変更しています
  • 彼らはimagesディレクトリにいくつかの画像を追加しています(しかしソース管理下でそれらを追加することを忘れています)
  • 彼らは後で私にメールで画像を送っています
  • 画像をソース管理下に追加し、他の変更と共にGitHubにプッシュします
  • Gitは自分のファイルを上書きしたくないので、GitHubから更新を引き出すことはできません。

これは私が得ているエラーです:

エラー:追跡されていない作業ツリーファイル 'public/images/icon.gif'はマージによって上書きされます

Gitにそれらを上書きさせるにはどうすればいいですか?人はデザイナーです - 通常、私はすべての衝突を手作業で解決しますので、サーバーには最新のバージョンがあり、それを自分のコンピューターで更新するだけです。

6088
Jakub Troszok

重要:ローカルの変更があると、それらは失われます。 --hardオプションがあってもなくても、プッシュされていないローカルコミットは失われます。[*]

Gitによって追跡されている not のファイル(アップロードされたユーザーコンテンツなど)がある場合、これらのファイルは影響を受けません。


これが正しい方法だと思います。

git fetch --all

次に、2つの選択肢があります。

git reset --hard Origin/master

または他の支店にいる場合は、

git reset --hard Origin/<branch_name>

説明:

git fetchは、マージやリベースを行わずに、最新のものをリモートからダウンロードします。

それからgit resetはマスターブランチをあなたが今フェッチしたものにリセットします。 --hardオプションは、作業ツリー内のすべてのファイルをOrigin/master内のファイルと一致するように変更します。


現在のローカルコミットを維持する

[*]:リセットする前にmasterからブランチを作成することで現在のローカルコミットを維持することが可能であることは注目に値します。

git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard Origin/master

これ以降、古いコミットはすべてnew-branch-to-save-current-commitsに保存されます。 

未確定の変更

コミットされていない変更は、(段階的であっても)失われます。必要なものを隠してコミットするようにしてください。そのためには、以下を実行することができます。

git stash

次に、これらのコミットされていない変更を再適用します。

git stash pop
8139
RNA

これを試して:

git reset --hard HEAD
git pull

それはあなたが望むことをするべきです。

808
Travis Reeder

警告:git cleanは追跡されていないファイル/ディレクトリをすべて削除するので、元に戻すことはできません。


clean -fだけではうまくいかない場合があります。ディレクトリを追跡していない場合は、-dオプションも必要です。

# WARNING: this can't be undone!

git reset --hard HEAD
git clean -f -d
git pull

警告:git cleanは追跡されていないファイル/ディレクトリをすべて削除するので、元に戻すことはできません。

最初に-n--dry-run)フラグを使用することを検討してください。これは実際に何も削除せずに削除されるものをあなたに示します。

git clean -n -f -d

出力例

Would remove untracked-file-1.txt
Would remove untracked-file-2.txt
Would remove untracked/folder
...
409

ハリネズミのように私は答えがひどいと思います。しかしHedgehogの答えはもっと良いかもしれませんが、私はそれがそれができるほどエレガントであるとは思いません。私がこれを行うために見つけた方法は、定義された戦略で "フェッチ"と "マージ"を使用することです。上書きを強制しようとしているファイルの1つではない限り、ローカルの変更は保持されるようになります。 

まずあなたの変更をコミットする

 git add *
 git commit -a -m "local file server commit message"

それから変更を取得し、衝突があれば上書きします

 git fetch Origin master
 git merge -s recursive -X theirs Origin/master

"-X"はオプション名、 "theirs"はそのオプションの値です。競合がある場合は、「あなたの」変更ではなく「彼らの」変更を使用することを選択しています。

347
Richard Kersey

する代わりに:

git fetch --all
git reset --hard Origin/master

私は次のことをすることをお勧めします:

git fetch Origin master
git reset --hard Origin/master

Origin/masterブランチにリセットするのであれば、すべてのリモートとブランチを取得する必要はありません。

251
Johanneke

最善の方法は、最初に行うことです。

git clean

追跡されていないファイルをすべて削除してから、通常のgit pull...に進みます。

125
Jakub Troszok

警告、gitignoreファイルにディレクトリ/ *エントリがある場合、これを行うとファイルが完全に削除されます。

いくつかの答えはひどいようです。 David Avsajanishviliの提案に従うことで、@ Lauriに何が起こったのかという意味でひどいです。

むしろ(git> v1.7.6):

git stash --include-untracked
git pull

後であなたは隠し場所の歴史をきれいにすることができます。

手動で1つずつ

$ git stash list
stash@{0}: WIP on <branch>: ...
stash@{1}: WIP on <branch>: ...

$ git stash drop stash@{0}
$ git stash drop stash@{1}

残忍なことに、一度に:

$ git stash clear

もちろん、あなたがあなたが隠したものに戻りたいならば:

$ git stash list
...
$ git stash apply stash@{5}
102
Hedgehog

このコマンドはローカルの変更を捨てるのに役立ちます。

git checkout <your-branch> -f

その後、クリーンアップを行います(追跡されていないファイルを作業ツリーから削除します)。

git clean -f

追跡されていないファイルに加えて追跡されていないディレクトリを削除する場合は、次の手順を実行します。

git clean -fd
88
Vishal

git pullとマージする代わりに、これを試してください: 

git fetch --all

に続く:

git reset --hard Origin/master

82
Lloyd Moore

私のために働いたことが唯一のものでした:

git reset --hard HEAD~5

これにより、5つのコミットが戻ってきます。

git pull

Gitマージを元に戻す方法 を調べてみました。

55
Chris BIllante

これらすべてのソリューションの問題点は、それらがすべて複雑すぎること、またはさらに大きな問題であるが、追跡されていないすべてのファイルがWebサーバーから削除されることです。 Gitリポジトリにはないサーバー。

これが私たちが使っている最もきれいな解決策です:

# Fetch the newest code
git fetch

# Delete all files which are being added, so there
# are no conflicts with untracked files
for file in `git diff HEAD..Origin/master --name-status | awk '/^A/ {print $2}'`
do
    rm -f -- "$file"
done

# Checkout all files which were locally modified
for file in `git diff --name-status | awk '/^[CDMRTUX]/ {print $2}'`
do
    git checkout -- "$file"
done

# Finally pull all the changes
# (you could merge as well e.g. 'merge Origin/master')
git pull
  • 最初のコマンドは最新のデータを取得します。

  • 2番目のコマンドは、リポジトリに追加されているファイルが存在するかどうかを確認し、競合の原因となる可能性のある未追跡ファイルをローカルリポジトリから削除します。

  • 3番目のコマンドは、ローカルに変更されたすべてのファイルをチェックアウトします。

  • 最後に最新バージョンに更新しますが、今回はリポジトリに存在する追跡されていないファイルはもう存在せず、すべてのローカルで変更されたファイルはすでにリポジトリと同じであるため、今回は競合はありません。

51

まず、標準的な方法を試してください。

git reset HEAD --hard # To remove all not committed changes!
git clean -fd         # To remove all untracked (non-git) files and folders!

警告:上記のコマンドは、コミットしていない場合にのみデータ/ファイルが失われる可能性があります!不明な場合は、リポジトリフォルダー全体の最初にバックアップを作成してください。

それからもう一度引っ張ります。

上記が役に立たず、追跡されていないファイル/ディレクトリを気にしない場合(念のためバックアップを最初に作成してください)、次の簡単な手順を試してください。

cd your_git_repo  # where 'your_git_repo' is your git repository folder
rm -rfv *         # WARNING: only run inside your git repository!
git pull          # pull the sources again

これにより、すべてのgitファイルが削除され(.git/ dirを除く、すべてのコミットがある場合)、再度プルされます。


なぜgit reset HEAD --hardが失敗する可能性があるのですか?

  1. .gitattributes fileのカスタムルール

    .gitattributesにeol=lfルールがあると、一部のテキストファイルでCRLFの行末をLFに変換することにより、gitがファイルの変更を変更する可能性があります。

    その場合は、これらのCRLF/LFの変更を(git statusで確認して)コミットするか、git config core.autcrlf falseを試して、一時的に無視してください。

  2. ファイルシステムの非互換性

    パーミッション属性をサポートしないファイルシステムを使用しているとき。例では、2つのリポジトリがあります。1つはLinux/Mac(ext3/hfs+)にあり、もう1つはFAT32/NTFSベースのファイルシステムにあります。

    お気づきのとおり、ファイルシステムには2種類あります。したがって、Unixのアクセス許可をサポートしていないシステムは、基本的に、そのようなアクセス許可をサポートしていないシステムのファイルアクセス許可をリセットできません。したがって、--hard試してみると、gitは常にいくつかの「変更」を検出します。

44
kenorb

私は同じ問題を抱えていました。誰も私にこの解決策を与えてくれませんでした、しかしそれは私のために働きました。

私はそれを解決しました:

  1. すべてのファイルを削除してください。 .gitディレクトリだけを残してください。
  2. git reset --hard HEAD
  3. git pull
  4. git Push

今それは働きます。

39

ボーナス:

前回の回答でpull/fetch/mergeをした際には、興味深く生産的なトリックを共有したいと思います。

git pull --rebase

上記のコマンドは、私のGitの人生で最も便利なコマンドで、多くの時間を節約しました。

新たにコミットをサーバーにプッシュする前に、このコマンドを試してください。そうすると、最新のサーバーの変更が自動的に同期され(フェッチ+マージ)、Gitログの一番上にコミットが置かれます。手動のプル/マージについて心配する必要はありません。

詳細は"git pull --rebase"で何ができますか?を参照してください。

33

私は同様の問題を抱えていました。私はこれをしなければなりませんでした:

git reset --hard HEAD
git clean -f
git pull
27
Ryan

私は他の答えをまとめました。 git pullをエラーなしで実行できます。

git fetch --all
git reset --hard Origin/master
git reset --hard HEAD
git clean -f -d
git pull

警告 :このスクリプトは非常に強力なので、変更を失う可能性があります。

27
Robert Moon

私自身の同様の経験に基づいて、上記のStrahinja Kustudicによって提供されたソリューションははるかに最高です。他の人が指摘したように、単にハードリセットをすることは all configファイルのようなあなたが削除したくないものを多く含むことができる追跡されていないファイルを削除するでしょう。より安全なのは、追加されようとしているファイルだけを削除することです。そのため、更新されようとしているローカルで変更されたファイルもチェックアウトすることをお勧めします。

それを念頭に置いて、私はKustudicのスクリプトを更新してまさにそれを実行しました。私はまたタイプミスを修正しました(オリジナルの 'missing')。

#/bin/sh

# Fetch the newest code
git fetch

# Delete all files which are being added,
# so there are no conflicts with untracked files
for file in `git diff HEAD..Origin/master --name-status | awk '/^A/ {print $2}'`
do
    echo "Deleting untracked file $file..."
    rm -vf "$file"
done

# Checkout all files which have been locally modified
for file in `git diff HEAD..Origin/master --name-status | awk '/^M/ {print $2}'`
do
    echo "Checking out modified file $file..."
    git checkout $file
done

# Finally merge all the changes (you could use merge here as well)
git pull
26
Rolf Kaiser

私は矛盾の2つの考えられる原因があると思います、それは別々に解決されなければなりません、そして、私が上記の答えのどれも言うことができない限り、両方を扱います:

  • 追跡されていないローカルファイルは、手動で(より安全に)または他の回答で示唆されているように、git clean -f -dによって削除する必要があります。

  • リモートブランチにないローカルコミットも削除する必要があります。 IMOはこれを達成する最も簡単な方法です:git reset --hard Origin/master( 'master'をあなたが取り組んでいるブランチに置き換えて、最初にgit fetch Originを実行してください)

23
tiho

もっと簡単な方法は、

git checkout --theirs /path/to/file.extension
git pull Origin master

これはあなたのローカルファイルをgitのファイルで上書きします

20
maximus 69

ここでの答えの大部分はmasterブランチに焦点を当てているようです。しかし、私は2つの異なる場所で同じ機能ブランチに取り組んでおり、フープを飛び越えることなく、一方にリベースをもう一方に反映させたい場合があります。

RNAの答え および 同様の質問に対するtorekの答え の組み合わせに基づいて、私はこれを見事に実現しました。

git fetch
git reset --hard @{u}

これをブランチから実行すると、ローカルブランチは上流のバージョンにリセットされるだけです。

これはgitエイリアス(git forcepull)にもうまく入れることができます。

git config alias.forcepull "!git fetch ; git reset --hard @{u}"

または、.gitconfigファイルで、

[alias]
  forcepull = "!git fetch ; git reset --hard @{u}"

楽しい!

20
JacobEvelyn

私は同じ問題を抱えていました、そして、何らかの理由で、git clean -f -dでもそれがしませんでした。その理由は以下のとおりです。何らかの理由で、ファイルがGitに無視された場合(.gitignoreエントリを介して)、それ以降のpullで上書きすることに悩まされますが、cleanはそうしません-xを追加しない限り、削除してください。

19
Tierlieb

私はちょうどこれで自分自身を解決しました:

git checkout -b tmp # "tmp" or pick a better name for your local changes branch
git add -A
git commit -m 'tmp'
git pull
git checkout master # Or whatever branch you were on originally
git pull
git diff tmp

最後のコマンドはあなたのローカルな変更が何であったかのリストを与えます。それが受け入れられるまで "tmp"ブランチを修正し続け、それからmasterにマージします。 

git checkout master && git merge tmp

次回は、 "git stash branch"を検索することで、これをよりクリーンな方法で処理できる可能性がありますが、最初の数回の試行でstashを使用すると問題が生じる可能性があります.

18
Simon B.

git cleangit resetも動かないという奇妙な状況があります。追跡されていないすべてのファイルに対して次のスクリプトを使用して、git indexから競合ファイルを削除する必要があります。

git rm [file]

それから私はうまく引っ張ることができます。

17
Chen Zhang

私ははるかに簡単で痛みの少ない方法を知っています。

$ git branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp

それでおしまい!

16
ddmytrenko

これらの4つのコマンドは私のために働きます。

git reset --hard HEAD
git checkout Origin/master
git branch -D master
git checkout -b master

これらのコマンドを実行した後にチェック/プルするには

git pull Origin master

私はたくさん試しましたが、ついにこれらのコマンドで成功しました。

13
vishesh chandra

やるだけ

git fetch Origin branchname
git checkout -f Origin/branchname // This will overwrite ONLY new included files
git checkout branchname
git merge Origin/branchname

だから、あなたが保持したいファイルやディレクトリを削除するなど、不要な副作用をすべて回避することができます。

12
user2696128

元の質問にもかかわらず、一番上の答えは同じような問題を抱えているが自分のローカルファイルを失いたくない人々にとって問題を引き起こす可能性があります。例えば、Al-PunkとcrizCraigのコメントを見てください。 

次のバージョンでは、ローカルの変更を一時的なブランチ(tmp)にコミットし、元のブランチ(私はmasterと仮定しています)をチェックアウトして更新をマージします。 stashでこれを行うことができますが、通常は単純に分岐/マージアプローチを使用する方が簡単であることがわかりました。

git checkout -b tmp
git add *; git commit -am "my temporary files"
git checkout master

git fetch Origin master
git merge -s recursive -X theirs Origin master

otherリポジトリ Origin masterであると仮定します。

12
Snowcrash

インデックスとヘッドをOrigin/masterにリセットしますが、作業ツリーはリセットしません。

git reset Origin/master
11
user811773

要件:

  1. ローカルの変更を追跡して、ここで誰もそれらを失わないようにします。
  2. ローカルリポジトリをリモートOriginリポジトリと一致させます。

溶液:

  1. Stashローカルの変更。
  2. フェッチ with clean of files and directories ignoring 。gitignore and ハードリセット to Origin.

    git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard Origin/master
    
9
vezenkov

私はすべての答えを読みましたが、これを実行するための単一のコマンドを探していました。これが私がしたことです。 .gitconfigにgitエイリアスを追加しました

[alias]
      fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f"

以下のようにコマンドを実行してください。 

git fp Origin master

に相当

git fetch Origin master
git reset --hard Origin/master
9
Venkat Kotra

git reset --hardを使用しないでください。それはそれらの変更を抹消するでしょう、そしてそれは全く望ましくないかもしれません。代わりに:

git pull
git reset Origin/master
git checkout <file1> <file2> ...

明らかにマージするつもりはないので、もちろんgit fetchの代わりにgit pullを使用することができますが、通常引っ張るならここで引っ張り続けることは意味があります。

それでここで起こることはgit pull があなたのOrigin/masterリファレンスを更新することです ; git reset あなたのローカルブランチの参照を更新します onファイルを更新せずにOrigin/masterと同じになるので、チェックアウトされた状態は変わりません。それからgit checkout ファイルをあなたのローカルブランチインデックス状態に戻します 必要に応じて。ライブとアップストリームのマスターでまったく同じファイルが追加されている場合、インデックスはリセット後のファイルとすでに一致しているので、通常はgit checkoutを実行する必要はまったくありません。

上流のブランチに自動的に適用したいコミットも含まれている場合は、プロセスの微妙な変化に従うことができます。

git pull
git merge <commit before problem commit>
git reset <problem commit>
git checkout <file1> <file2> ...
git pull
8
Jim Driscoll

これは変更を元に戻すためのベストプラクティスです。

  • git commit段階的な変更をコミットして、それらがreflog)に保存されるようにします(下記参照)。
  • git fetch最新のアップストリームの変更を取得する
  • git reset --hard Origin/master Originマスターブランチへのハードリセット

reflogローカルリポジトリで更新されているブランチやその他の参照を記録します。あるいは単純に - reflogあなたの変更履歴)です。

だからコミットすることは常に素晴らしい習慣です。コミットがreflogに追加されるので、削除されたコードを常に取得することができます。

7
Jordan Georgiev

このコマンドを使用してローカルファイルを削除し、プル/マージを実行できないようにしました。しかし注意してください。最初にgit merge …を実行して、本当に削除したいファイルだけがあるかどうかを確認してください。

git merge Origin/master 2>&1 >/dev/null | grep ^[[:space:]] | sed s/^[[:space:]]//g | xargs -L1 rm
  • git mergeは、とりわけそれらすべてのファイルをリストします。それらはいくつかの空白が先頭に付きます。
  • 2>&1 >/dev/nullはエラー出力を標準のエラー出力にリダイレクトするので、grepによって拾われます。
  • grep ^[[:space:]]は、ファイル名を持つ行のみをフィルタリングします。
  • sed s/^[[:space:]]//gは、空白を最初から削除します。
  • xargs -L1 rmはそれらの各ファイルに対してrmを呼び出し、それらを削除します。

注意して処理する:git mergeが出力するものは何でも、rmは空白で始まる every 行に対して呼び出されます。

5
Glutexo

Angular 2-Webpack-StarterのMaterial2ブランチを使おうとしていましたが、ちょっと時間がかかりました。これが私がそのブランチをダウンロードして使用できる唯一の方法でした。

git clone --depth 1 https://github.com/angularclass/angular2-webpack-starter.git

cd angular2-webpack-starter/

git checkout -b material2

プロジェクトフォルダを開き、隠されていないファイルとフォルダをすべて削除します。隠されたものはすべて残してください。

git add .

git commit -m "pokemon go"

git reset --hard

git pull Origin material2

(エディタが表示されたら、 ':wq'を押してからを押します。 Enter

これで準備は整いました。

5
Helzgate

Windowsでは、次の単一のコマンドを実行してください。

git fetch --all & git reset --hard Origin/master
3
Luca C.

プロジェクトのベースフォルダにあるファイルでそのファイルを無視することができます。

.gitignore

public/images/*

それから変更を引っ張り、それからgitignoreファイルからその行を削除します。

3
Daniel Gaytán

git fetch --all && git reset --hard Origin/master && git pull

0
Suge

1:前のコミットにリセット

git reset --hard HEAD

2:追跡できないファイルを削除する

git clean -f

3:コミットをやめる

git pull

出典:

0
abhijithvijayan

試すことができます

git pull --force

すべてのローカルファイルを上書きする場合

0
Ultan Kearns
git fetch --all

その後、マスターブランチにいる場合

git reset --hard Origin/master

else

git reset --hard Origin/master<branch_name>
0

一般的な方法でリモートトラッキングブランチにリセットしたい場合は、次のようにします。

git fetch
git reset --keep Origin/$(git rev-parse --abbrev-ref HEAD)

ローカルの変更もリセットしたい場合は、

git fetch
git reset --hard Origin/$(git rev-parse --abbrev-ref HEAD)
0
warch