如何強制“ git pull”覆蓋本地文件?

How do I force “git pull” to overwrite local files?
投票:6504回答:42

如何在git pull上強制覆蓋本地文件?

該場景如下:

  • 團隊成員正在修改我們正在工作的網站的模板
  • 他們正在將一些圖像添加到圖像目錄(但是忘記在源代碼控制下添加它們)
  • 他們通過郵件將圖像發送給我
  • 我將圖像添加到源代碼管理下,並將其與其他更改一起推送到GitHub
  • 他們無法從GitHub提取更新,因為Git不想覆蓋其文件。

這是我得到的錯誤:

錯誤:未跟踪的工作樹文件“ public / images / icon.gif”將被合併覆蓋

如何強制Git覆蓋它們? 這個人是設計師-通常我會手工解決所有衝突,因此服務器具有他們只需在計算機上更新的最新版本。

tags:git,version-control,overwrite,git-pull,git-fetch
42回答
367
投票

像刺猬一樣,我認為答案很糟糕。 但是,儘管刺猬的答案可能更好,但我認為它並沒有它的優雅。 我發現做到這一點的方法是通過使用已定義策略的“提取”和“合併”。 應該這樣做,以便保留本地更改,只要它們不是您要強制覆蓋的文件之一即可。

首先提交您的更改

 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”是該選項的值。 如果發生衝突,您選擇使用“他們的”更改,而不是“您的”更改。


128
投票

看來最好的方法是先這樣做:

git clean

要刪除所有未跟踪的文件,然後繼續執行常規的git pull ...


48
投票

首先,嘗試標準方法:

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規則可能會導致git通過將某些文本文件中的CRLF行尾轉換為LF來修改某些文件更改。

    如果是這樣,您必須提交這些CRLF / LF更改(通過在git status查看它們),或嘗試: git config core.autcrlf false以暫時忽略它們。

  2. 文件系統不兼容

    當您使用不支持權限屬性的文件系統時。 在示例中,您有兩個存儲庫,一個在Linux / Mac( ext3 / hfs+ )上,另一個在基於FAT32 / NTFS的文件系統上。

    你可能注意到了,有兩種不同類型的文件系統,所以一個不支持Unix許可基本上不能在系統復位文件權限不支持那種權限的,所以無論怎麼--hard你嘗試一下,git總是檢測到一些“變化”。


52
投票

所有這些解決方案的問題在於它們要么太複雜,要么甚至更大的問題是它們從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
  • 第一條命令獲取最新數據。

  • 第二個命令檢查是否有任何文件要添加到存儲庫中,並從本地存儲庫中刪除那些會引起衝突的未跟踪文件。

  • 第三個命令檢出所有在本地修改的文件。

  • 最後,我們拉動更新到最新版本,但是這次沒有任何衝突,因為回購中不再存在未跟踪的文件,並且所有本地修改的文件已經與存儲庫中的相同。


84
投票

而不是與git pull合併,請嘗試以下操作:

git fetch --all

其次是:

git reset --hard origin/master


11
投票

將索引和標頭重置為origin/master ,但不要重置工作樹:

git reset origin/master

27
投票

根據我自己的類似經驗,上述Strahinja Kustudic提供的解決方案是迄今為止最好的。 正如其他人指出的那樣,僅執行硬重置將刪除所有未跟踪的文件,這些文件可能包含許多您不想刪除的內容,例如配置文件。 更為安全的是僅刪除將要添加的文件,因此,您可能還希望檢出將要更新的所有本地修改的文件。

考慮到這一點,我更新了Kustudic的腳本來做到這一點。 我還修正了一個拼寫錯誤(原文中缺少“”)。

#/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

266
投票

而不是做:

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

我建議您執行以下操作:

git fetch origin master
git reset --hard origin/master

如果您要重置為Origin / master分支,就不需要獲取所有的遙控器和分支嗎?


20
投票

似乎大多數答案都集中在master分支上。 但是,有時候我在兩個不同的地方處理同一個功能分支,並且我希望其中一個的基礎能夠在另一個中得到反映,而不會造成很大的麻煩。

基於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}"

請享用!


13
投票

這四個命令對我有用。

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

執行這些命令後進行檢查/拉動

git pull origin master

我做了很多嘗試,但最終在這些命令上獲得了成功。


13
投票

儘管有最初的問題,但是對於有類似問題但又不想丟失其本地文件的用戶,最重要的答案可能會引起問題。 例如,請參閱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

我們假設另一個存儲庫origin master


867
投票

嘗試這個:

git reset --hard HEAD
git pull

它應該做您想要的。


21
投票

一種更簡單的方法是:

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

這將用git上的文件覆蓋您的本地文件


27
投票

我總結了其他答案。 您可以執行git pull而不會出現錯誤:

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

警告 :此腳本非常強大,因此您可能會丟失所做的更改。


9
投票

要求:

  1. 跟踪本地更改,因此這裡沒有人會丟失它們。
  2. 使本地存儲庫與遠程原始存儲庫匹配。

解:

  1. 隱藏本地更改。
  2. 乾淨的 文件目錄忽略的.gitignore硬復位 原產獲取

     git stash --include-untracked git fetch --all git clean -fdx git reset --hard origin/master 

18
投票

我知道一種更簡單,更輕鬆的方法:

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

而已!


12
投票

做就是了

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

因此,您可以避免所有不必要的副作用,例如刪除要保留的文件或目錄等。


90
投票

您可能會發現此命令有助於丟棄本地更改:

git checkout <your-branch> -f

然後進行清理(從工作樹中刪除未跟踪的文件):

git clean -f

如果要除去未跟踪文件之外的其他未跟踪目錄,請執行以下操作:

git clean -fd

36
投票

獎金:

在前面的答案中提到拉取/獲取/合併時,我想分享一個有趣且富有成效的技巧,

git pull --rebase

上面的命令是我的Git生命中最有用的命令,它節省了很多時間。

在將新提交的內容推送到服務器之前,請嘗試使用此命令,它將自動同步最新的服務器更改(通過訪存+合併),並將您的提交內容放在Git日誌的頂部。 無需擔心手動拉/合併。

“ git pull --rebase”做什麼中找到詳細信息


9
投票

我通讀了所有答案,但我正在尋找一個命令來執行此操作。 這是我所做的。 為.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

18
投票

我自己通過以下方法解決了這個問題:

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可能會給您帶來麻煩,因此,請首先在非關鍵項目上進行實驗...


45
投票

我有同樣的問題。 沒有人給我這種解決方案,但是對我有用。

我通過以下方法解決了它:

  1. 刪除所有文件。 僅保留.git目錄。
  2. git reset --hard HEAD
  3. git pull
  4. git push

現在可以了。


27
投票

我有一個類似的問題。 我必須這樣做:

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

437
投票

警告: 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
...

58
投票

唯一對我有用的是:

git reset --hard HEAD~5

這將帶您退回五次提交,然後

git pull

通過查找如何撤消Git合併 ,我發現了這一點。


19
投票

我遇到了同樣的問題,由於某種原因,即使是git clean -f -d也不會這樣做。 這是為什麼:由於某種原因,如果您的文件被Git忽略(我認為是通過.gitignore條目),它仍然會為以後的pull重寫而煩惱,但是除非您添加-x ,否則乾淨不會刪除它。


17
投票

我有一個奇怪的情況,無論是git clean還是git resetgit clean 我必須通過在每個未跟踪的文件上使用以下腳本從git index刪除衝突的文件:

git rm [file]

然後我可以拉得很好。


23
投票

我相信有兩種可能的衝突原因,必須分別解決,據我所知,上述答案均未涉及這兩種問題:

  • 需要手動刪除(更安全)或按照其他答案的建議,通過git clean -f -d刪除未跟踪的本地文件。

  • 不在遠程分支上的本地提交也需要刪除。 IMO實現此目的最簡單的方法是: git reset --hard origin/master (用正在處理的任何分支替換“ master”,然後首先運行git fetch origin


9067
投票

重要提示:如果您進行任何本地更改,它們將會丟失。 無論是否使用--hard選項,所有尚未推送的本地提交都將丟失。 [*]

如果您有Git 不能跟踪的任何文件(例如,上載的用戶內容),這些文件將不會受到影響。


我認為這是正確的方法:

git fetch --all

然後,您有兩個選擇:

git reset --hard origin/master

或如果您在其他分支機構:

git reset --hard origin/<branch_name>

說明:

git fetch從遠程下載最新版本,而無需嘗試合併或重新設置任何內容。

然後git reset將master分支重置為您剛剛獲取的分支。 --hard選項更改工作樹中的所有文件以匹配origin/master文件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

107
投票

警告,如果您在gitignore文件中有任何目錄/ *條目,這樣做將永久刪除您的文件。

一些答案似乎很糟糕。 在遵循David Avsajanishvili的建議後,@ Lauri發生了什麼事情,真是太糟糕了。

而是(git> v1.7.6):

git stash --include-untracked
git pull

稍後,您可以清除存儲歷史記錄。

手動一對一:

$ 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}

©2020 sofbug.com - All rights reserved.