16

というJavaファイルがありましたpackage/old/myfile.java。このファイルを git でコミットしました。次に、パッケージの名前を に変更しnewて、ファイルがpackage/new/myfile.java.

このファイルの名前変更 (およびコンテンツの変更) を git にコミットしたいと思います。

私がするとき、私はgit status得る

# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       deleted:    package/old/myfile.java
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       package/new/myfile.java

私はadd新しいものとrm古いものを試してみましたが、その逆も同様です。

$ git status
# On branch develop
# Changes to be committed: 
#        delete:    package/old/myfile.java
#        new file:  package/new/myfile.java

mv old new古いファイルが存在しないため実行できず、bad sourceエラーが発生します。

他に試せることはありますか?

同様の問題についてSOで複数の回答をいくつか試しましたが、うまくいきませんでした。

4

3 に答える 3

19

git book関連セクションでこれについて説明しています。

他の多くの VCS システムとは異なり、Git はファイルの移動を明示的に追跡しません。Git でファイルの名前を変更した場合、ファイルの名前を変更したことを示すメタデータは Git に保存されません。ただし、Git は事後にそれを理解することについては非常に賢明です。ファイルの動きの検出については、少し後で説明します。

これが意味することは、ファイルを移動してから大幅な変更を加えた場合、git はそれが移動であったことを認識できないということです。新しいファイルは古いファイルのように見えないため、ファイルが削除され、新しいファイルが作成されます。この問題を回避するにgit mvは、ファイルを作成し、移動をコミットしてから、変更を加えることがよくあります。あなたの状況でできること

git reset # Move changes from index to working copy
git checkout package/old/myfile.java # Undo delete
git mv package/old/myfile.java package/new/myfile.java # Move file
于 2013-01-25T17:42:00.667 に答える
7

ファイルを元に戻してからコミットし、実際の移動を別のコミットに入れます。Git は移動 (または名前変更) 自体を記録しませんが、後でコンテンツに基づいて認識できます。内容が変化すると、動きを正しく検出できません。したがって、移動と変更を 2 つのコミットに分割するのが一般的です。

于 2013-01-25T17:37:01.950 に答える
3

@Nevik Rehnel の 2 つのコミットの提案を、編集前にファイルを移動するように履歴を書き換えて実装するコマンド:

開始条件:

  • 最新のコミットには、ファイルへの移動と変更の両方が含まれておりgit log --follow newpath、ファイルは最新のコミットで新しく作成されたものとして表示されます

手順:

  • 現在のステータスにタグを付けるgit tag working_code
  • インタラクティブなリベースを開始して、履歴を編集します。git rebase -i HEAD~2
    • ポップアップするエディターで、最初の行の「pick」を「edit」に変更し、保存して終了します。
  • コミットの直前に履歴を編集しています
  • 独自のコミットとして移動を作成する
    • git mv oldpath newpath
    • 新しいファイルの場所を含むディレクトリが存在する必要があります。あなたはmkdir最初にそれをしなければならないかもしれません
    • (オプション) ファイルの名前変更に伴う必要な小さな変更を加えてファイルを編集します (例: Java では、クラス名および/またはパッケージおよびインポート行) -他の変更を避けるGit は類似性に基づいてこれらを同じファイルとして検出します
    • git add .次のように表示されることを確認しgit statusます。renamed: oldpath -> newpath
    • git commit -m "Rename oldpath newpath"
  • git rebase --continue
    • newpath で競合が発生するはずです。でファイルを復元しますgit checkout working_code newpath
    • リベースを完了します。git rebase --continue
  • git log --follow newpath完全な履歴が表示されることを確認します
于 2015-07-24T21:26:00.963 に答える