web-dev-qa-db-ja.com

Perforceユーザー向けのGit

私は長年Perforceを使用しています。私は個人的なコードにgitを使用するように切り替えたいと思いますが、これまで見てきたすべてのgitチュートリアルは、完全なソース管理n00b(非常に退屈な作業)であるか、またはsvn(私は違います)。

私はp4を知っており、分散ソース管理システムの背後にある考え方も理解しています(したがって、売り込みは必要ありません、ありがとう)。私が望むのは、p4コマンドから同等のgitコマンドへの変換テーブルと、同等のp4を持たない "ca n't live live"コマンドです。

私はすべてのp4ユーザーがp4の異なるサブセットを使用していると思うので、ここで私がgitでできるようにしたいことをp4で定期的に行っていますが、これは私が見たドキュメントからすぐにはわかりません:

  1. 単一のクライアントに複数の保留中のチェンジリストを作成します。 (p4 change
  2. 保留中のチェンジリストを編集します。 (p4 change
  3. すべての保留中のチェンジリストのリストを見る(p4 changes -s pending
  4. クライアント(p4 opened)または保留中のチェンジリスト(p4 describe)で変更されたすべてのファイルのリスト
  5. 保留中のチェンジリストの差分を参照(p4 diffおよびp4 describeを使用するラッパースクリプトを使用)
  6. 特定のファイルについて、どのサブミット済みチェンジリストがどの行に影響したかを確認します(p4 annotate
  7. 特定のファイルについては、ファイルに影響を与えたチェンジリストの説明のリストを参照してください(p4 log
  8. 保留中のチェンジリストを送信(p4 submit -c
  9. 保留中のチェンジリストを中止します(p4 revert

これらの多くは「チェンジリスト」を中心に展開しています。 「チェンジリスト」はp4の用語です。 gitの同等の用語は何ですか?

ブランチは、p4がチェンジリストと呼ぶものの代わりにgitユーザーが使用するもののようです。 p4にはブランチと呼ばれるものもありますが、それらは漠然と関連した概念にすぎないように見えますが、少し混乱します。 (p4のブランチという概念はかなり奇妙だといつも思っていましたが、古典的なRCSブランチという概念とはまた違っています。)

とにかく... gitのブランチを使用してp4チェンジリストで通常行うことをどのように達成するかわからない。 p4では、次のようなことができます。

$ p4 edit a.txt
$ p4 change a.txt
Change 12345 created.

この時点で、a.txtを含む変更リストがあります。変更リストを送信せずに説明を編集して作業を続けることができます。また、コードの他のレイヤーのバグ修正など、他のファイルに変更を加える必要があることが判明した場合、同じクライアントでそれを行うことができます:

$ p4 edit z.txt
$ p4 change z.txt
Change 12346 created.

これで、同じクライアントに2つの別々のチェンジリストができました。これらの作業を同時に行うことができ、それらを「切り替える」ために何もする必要はありません。コミットするときが来たら、それらを個別に送信できます。

$ p4 submit -c 12346  # this will submit the changes to z.txt
$ p4 submit -c 12345  # this will submit the changes to a.txt

これをgitで複製する方法がわかりません。私の実験では、git addが現在のブランチに関連付けられているようには見えません。私が知る限り、git commitを実行すると、その時点でどのブランチにいてもgit add- edしたすべてのファイルをコミットします。

$ git init
Initialized empty Git repository in /home/laurence/git-playground/.git/
$ ls
a.txt  w.txt  z.txt
$ git add -A .
$ git commit
 Initial commit.
 3 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 a.txt
 create mode 100644 w.txt
 create mode 100644 z.txt
$ vi a.txt z.txt 
2 files to edit
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   a.txt
#   modified:   z.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git branch aardvark
$ git checkout aardvark
M   a.txt
M   z.txt
Switched to branch 'aardvark'
$ git add a.txt 
$ git checkout master
M   a.txt
M   z.txt
Switched to branch 'master'
$ git branch zebra
$ git checkout zebra
M   a.txt
M   z.txt
Switched to branch 'zebra'
$ git add z.txt 
$ git status
# On branch zebra
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   a.txt
#   modified:   z.txt
#
$ git checkout aardvark
M   a.txt
M   z.txt
Switched to branch 'aardvark'
$ git status
# On branch aardvark
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   a.txt
#   modified:   z.txt

この例では、aardvarkブランチとzebraブランチにまったく同じ変更セットが含まれているように見え、git statusの出力に基づいて、どちらでコミットしても同じ効果があるように見えます。私は何か間違っていますか?

83

私はperforceをあまり使用していないので、これは正確には1:1の翻訳ではないかもしれません。再び、gitやMercurialのような分散ソース管理システムは、とにかく異なるワークフローを持っているので、実際には1:1の翻訳はありません(そうすべきではありません)。とにかく、ここに行きます:

  • 複数の保留中のチェンジリストを作成->代わりにブランチを使用します。 gitでは、ブランチは軽くて速く、作成に1秒未満、通常はマージに2秒未満かかります。分岐を恐れず、頻繁にリベースしてください。

    git branch new-branch-name
    git checkout new-branch-name
    

    または、すべてを1行で実行します。

    git checkout -b new-branch-name
    
  • すべての保留中のチェンジリストのリストを見る->複数の保​​留中のチェンジリストに相当するのは複数のブランチなので、ブランチを表示するだけです:

    git branch
    

    リモートブランチも表示したい場合:

    git branch -a
    

    マージが正常に完了したらすぐにブランチを削除することをお勧めします。これにより、マージされるブランチとマージ済みのブランチを追跡する必要がなくなります。

  • すべての変更されたファイルを一覧表示する->特定のブランチで保留中の単一の「チェンジリスト」の場合、gitにはインデックスまたはキャッシュの概念があります。変更をコミットするには、最初にこのインデックスにファイルを追加する必要があります。これにより、単一の変更を表すファイルのグループを手動で選択したり、無関係なファイルを無視したりできます。どのファイルが追加されたか、またはこのインデックスに追加されていないかを確認するには、次のようにします。

    git status
    
  • 保留中のチェンジリストの差分を見る->これには2つの部分があります。まず、作業ディレクトリとインデックスの差分を確認します。

    git diff
    

    ただし、現在入力している内容と最後のコミットの差分を知りたい場合は、作業ディレクトリとインデックスとHEADの差分を実際に求めています。

    git diff HEAD
    
  • 特定のファイルについて、どのサブミット済みチェンジリストがどの行に影響したかを確認します->これは簡単です:

    git blame filename
    

    または、ウィンドウ環境にいる場合はさらに良い:

    git gui blame filename
    

    Git guiはファイルの解析に時間がかかります(Cではなくtclで記述されています)が、コミットIDをクリックして過去に「タイムトラベル」する機能など、多くの機能があります。特定のバグが最終的に解決される方法を見つけることができるように、未来への「タイムトラベル」機能を実装したいだけです。

  • 特定のファイルについては、ファイルに影響を与えたチェンジリストの説明のリストを参照してください。

    git log filename
    

    しかし、git logはこれよりもはるかに強力なツールです。実際、私の個人的なスクリプトのほとんどは、gitログから便乗してリポジトリを読み取ります。 manページを読んでください。

  • 保留中のチェンジリストを送信->簡単:

    git commit
    

前の質問に対する私の答えを見て、私の典型的なgitワークフローを確認してください。 Gitを学ぶ。正しい軌道に乗っているかどうかを知る必要がある

私が概説したワークフローに従うと、gitkのようなツールは、変更のグループを明確に見ることができるため、はるかに価値があることがわかります。


追加の回答:

Gitは非常に柔軟性があり、説明したことを実行する方法がいくつかあります。覚えておくべきことは、作業中の機能ごとに常に新しいブランチを開始することです。これは、masterブランチは変更されないため、いつでも戻ってバグ修正を行えることを意味します。 gitでの作業は、ほとんど常に次のように始める必要があります。

git checkout -b new-feature-a

これで、ファイルa.txtを編集できます。別の機能で同時に作業するには、次のようにします。

git checkout master
git checkout -b new-feature-z

これで、ファイルz.txtを編集できます。 a.txtに戻すには:

git checkout new-feature-a

しかし、待ってください。new-feature-zに変更があり、gitではブランチを切り替えられません。この時点で、2つの選択肢があります。 1つ目は最も単純で、すべての変更を現在のブランチにコミットします。

git add .
git commit
git checkout new-feature-a

これは私が推奨するものです。しかし、実際にコードをコミットする準備ができていない場合は、一時的にそれを隠しておくことができます。

git stash

これで、ブランチnew-feature-aに切り替えることができます。作業していたコードに戻るには、スタッシュをポップするだけです。

git checkout new-feature-z
git stash pop

すべてが完了したら、すべての変更をマスターにマージして戻します。

git merge --no-ff new-feature-a
git merge --no-ff new-feature-z

マージは非常に迅速かつ簡単であるため(競合は非常にまれであり、競合の解決は簡単であるため、発生した場合はそれほど難しくないため)、すべてにgitのブランチを使用します。

他のソース管理ツールには見られないgitのブランチの一般的な使用の別の例を次に示します(おそらくMercurialを除く)。

開発環境を反映するために構成ファイルを変更し続ける必要がありますか?次に、ブランチを使用します。

git checkout -b dev-config

次に、お気に入りのエディターで構成ファイルを編集し、変更をコミットします。

git add .
git commit

これで、すべての新しいブランチはマスターの代わりにdev-configブランチから開始できます:

git checkout dev-config
git checkout -b new-feature-branch

完了したら、対話型リベースを使用してdev-configの編集をnew-feature-branchから削除します。

git rebase -i master

不要なコミットを削除してから保存します。これで、カスタム設定を編集せずにきれいなブランチができました。マスターにマージする時間:

git checkout master
git merge --no-ff new-feature-branch
# because master have changed, it's a good idea to rebase dev-config:
git checkout dev-config
git rebase master

git rebase -iを使用した編集の削除は、すべての変更が同じファイルで発生した場合でも機能することに注意してください。 Gitはファイルの内容ではなく、変更を記憶します*。

*注:実際には、技術的には完全に真実ではありませんが、ユーザーとしてはそのように感じます


追加の回答:

したがって、コメントからは、2つのブランチを同時に存在させて、結合されたコードがどのように機能するかをテストしたいようです。さて、これはブランチの力と柔軟性を示す良い方法です。

最初に、安価な分岐と変更可能な履歴がワークフローに与える影響についての言葉。 CVSとSVNを使用していたとき、私はいつもコミットすることに少し消極的でした。それは、不安定なコードをコミットすると、必然的に他の人の作業中のコードが処理されるためです。しかし、gitを使用すると、その恐怖を失いました。これは、gitで他の人がマスターにマージするまで私の変更を取得できないためです。だから今、私は自分が書いている5行ごとにコードをコミットしていることに気付きます。コミットするために完全な先見の明は必要ありません。考え方を変更するだけです:commit-to-branch == add-to-changeset、merge-to-master == commit-changeset。

それでは、例に戻りましょう。ここに私がそれをする方法があります。ブランチnew-feature-zがあり、new-feature-aでテストしたいとします。私はそれをテストするために新しいブランチを作成するだけです:

# assume we are currently in branch new-feature-z
# branch off this branch for testing
git checkout -b feature-z-and-feature-a
# now temporarily merge new-feature-a
git merge --no-ff new-feature-a

これでテストできます。 feature-zをfeature-aで動作させるために何かを変更する必要がある場合は、そうします。その場合、変更を関連するブランチにマージして戻すことができます。 git rebase -iを使用して、マージから無関係な変更を削除します。

または、git rebaseを使用して、new-feature-zのベースを一時的に変更して、new-feature-aを指すようにすることもできます。

# assume we are currently in branch new-feature-z
git rebase new-feature-a

ブランチの履歴が変更され、new-feature-zがmasterではなくnew-feature-aに基づいているようになりました。これでテストできます。このブランチでコミットされた変更は、ブランチnew-feature-zに属します。 new-feature-aを変更する必要がある場合は、元の機能に切り替えてリベースし、新しい変更を取得します。

git checkout new-feature-a
# edit code, add, commit etc..
git checkout new-feature-z
git rebase new-feature-a
# now new-feature-z will contain new changes from new-feature-a

完了したら、マスターにリベースして、new-feature-aから変更を削除します。

# assume we are currently in branch new-feature-z
git rebase master

新しいブランチを始めることを恐れないでください。スローアウェイブランチを始めることを恐れないでください。枝を捨てることを恐れないでください。そして、merge == submitとcommit == add-to-changesetは頻繁にコミットすることを恐れません。コミットは開発者の究極の取り消しツールです。

ああ、もう1つ、gitで削除されたブランチはまだリポジトリに存在しています。したがって、後で有用であるとわかったものを誤って削除した場合、履歴を検索することでいつでも元に戻すことができます。枝を捨てることを恐れないでください。

70
slebetman

Gitブランチとまったく同じではない「チェンジリスト」の概念がないため、私はあなたのように苦しんでいます。

そのチェンジリスト内のファイルのリストを含むチェンジリストファイルを作成する小さなスクリプトを作成します。

Git commit -a @ change_list_contents.txtを呼び出してから「git commit」を呼び出すだけで、特定のチェンジリストのみを送信する別のコマンド

エリアスがお役に立てば幸いです

1

Gitには、ワークフローの一部を形成できる、より軽量な代替手段があります。 gitステージング領域を使用します。

私は頻繁に変更を加えてから、いくつかのコミットとして送信します(たとえば、デバッグステートメントの追加、リファクタリング、実際のバグ修正)。 PERFORCEチェンジリストを設定してから変更を行ってから送信するのではなく、変更を加えてから送信方法を選択することができます(オプションでgitステージング領域を使用)。

コマンドラインから特定のファイルをコミットするには:

git commit a.txt
git commit z.txt

または、最初にファイルを明示的にステージングします。

git add a.txt
git commit
git add z.txt
git commit

git guiを使用すると、ファイル内から行またはハンクを選択して、ステージング領域でコミットを構築できます。これは、異なるコミットにしたい1つのファイルに変更がある場合に非常に便利です。 gitからperforceに移行したことは、私が本当に恋しいことの1つです。

このワークフローには、注意すべき小さな注意事項があります。ファイルに変更AとBを加え、ファイルをテストし、Aをコミットした場合、そのコミットをテストしていません(Bとは無関係)。

1
Russell Gallop

実際のチートシートを作成するのに十分なp4の経験はありませんが、少なくともいくつかの類似点があります。 p4 "changeset"はgit "commit"です。

ローカル作業スペースへの変更はgit addで「インデックス」に追加され、インデックスは後でgit commitでコミットされます。そのため、すべての意図と目的のために、インデックスは保留中のチェンジリストです。

git diffおよびgit statusで変更を確認します。ここで、git diffは通常、ワークスペースとインデックス間の変更を示しますが、git diff --cachedはインデックスとリポジトリ間の変更を示します(=保留中のチェンジリスト)。

詳細については、 http://progit.org/book/ をお勧めします。一般にバージョン管理を知っているので、おそらくそれの多くをざっと見て、git固有の情報を抽出することができます...

1
Jakob Borg

これは具体的にあなたの質問には答えませんが、Perforceの2ユーザー、5ワークスペースバージョンが perforce website から無料でダウンロードして使用できることを知っているかどうかはわかりません。

このようにして、必要に応じて自宅で個人のプロジェクトにperforceを使用できます。厄介な点の1つは、5つのワークスペースであり、多少制限がありますが、家庭での使用にperforceを使用できることは非常に信じられません。

0
Toby Allen

Perforceとgitの両方をかなり広範囲に使用してきたので、gitでPerforceチェンジリストの近くに行く方法は1つしかありません。

最初に理解すべきことは、この機能をgitで正しく実装することです。これは完全なクルージではありません。それを枝に靴べらにしようとすると、次の変更が必要になります:gitは単一の枝に複数のステージング領域を必要とします。

PERFORCEチェンジリストは、gitに同等のものがないワークフローを許可します。次のワークフローを検討してください。

Check out a branch
Modify file A and add it to changelist 1
Modify file B and add it to changelist 2

Gitのブランチを使用してこれを実行しようとすると、2つのブランチが作成されます。1つのブランチにはファイルAへの変更があり、もう1つのブランチにはファイルBへの変更がありますが、 ABの両方のファイルへの変更を同時に確認できる場所。

最も近い近似は、git add . -pを使用し、'a'および'd'サブコマンドを使用してファイル全体を選択または拒否することです。しかし、それはまったく同じではなく、ここでの違いは、2つのシステムの一般的な手口の根本的な違いに起因しています。

Git(およびこの議論にとって重要ではないSubversion)を使用すると、このことを事前に誰にも通知せずにファイルを変更できます。ファイルを変更するだけで、変更をコミットするときにgitですべてを整理できます。 Perforceでは、変更が許可される前にファイルを積極的にチェックアウトする必要があります。このため、チェンジリストが存在する必要があります。本質的に、Perforceでは、ファイルを変更する前にインデックスに追加する必要があります。したがって、Perforceで複数のチェンジリストが必要であり、gitに同等のものがない理由もあります。 単にそれらを必要としません。

0
dgnuff