web-dev-qa-db-ja.com

誰もがマスターで作業しているときにgitの痛みを最小限に抑えるにはどうすればよいですか?

最近、約10人のドキュメントチームがSVNからGitに移行しました。 SVNでは、誰もがマスターに取り組みました。これは、私がいつも嫌っていたモデルですが、その変化をもたらすことはできませんでした。 Gitへの移行の一環として、これを修正することに同意しましたが、まだそれを行うことはできません(任意のブランチからのビルドを可能にするビルドの変更を待機しています)。一方、誰もがマスターに取り組んでいます。はい、私はこれがひどいことを知っています、私を信じてください。

現在、SVNを使用していたときよりも多くの問題が発生しています。その一部は、Gitの2段階モデル​​(ローカルとリモート)が原因です。時々人々はコミットするがプッシュに失敗するか、彼らは引っ張って保留中のローカルな変更と衝突します。昨日、誰かが最近の変更を何らかの形で覆しました-どういうわけか-マージが失敗しました。これは、Gitがプルして優れた変更を行ったときに行われたマージであったと思います。 (彼は彼が何をしたのか正確に私に言うことができませんでした、そして彼はGUIを使用しているので私は彼のシェルの履歴を単に調べることはできません。)

最も熟練したGitユーザー(読んだもの:以前に使用したことがあるが、非常に複雑なものではない)として、私はポリシーを設定し、ツールを教え、混乱を片付ける人です。ブランチでの開発に切り替えるまで、ツールを使用して共有アクティブマスターをエラーが発生しにくくする方法にどのような変更を加えることができますか?

チームはWindowsでTortoise Gitを使用しています。以前Tortoise SVNを使用したため、Tortoise Gitを使用しています。 ([〜#〜] i [〜#〜]一部の操作ではCygwinの下でコマンドラインを個人的に使用しますが、チームはGUIが必要であることを明確にしており、これを使用します。 )回答はこのツールで機能する必要があり、置換を提案するものではありません。

Tortoise Gitには「コミット&プッシュ」が1つの操作として用意されており、常に実行するように指示しています。ただし、アトミックではありません。コミット(結局のところローカル)は問題なく機能しますが、プッシュが機能しない(たとえば、競合やネットワークの問題が原因)場合があります。その場合、あいまいなエラーが発生します。私は、最近のコミットについてany疑いがある場合はBitBucketコミットログを確認し、それが表示されない場合はプッシュするように彼らに伝えました。 (それが問題である場合は競合を解決するため、または何をすべきかわからない場合は助けを求めます。)

チームはすでに「早い段階で頻繁に引く」という良い習慣を持っています。しかし、プルは競合を引き起こす可能性があるようですが、これは新しいことだと思いますか?新しくない場合は、SVNよりも頻繁です。 Gitがプルする方法(マージではなくリベース)を変更できると聞きましたが、そこでのトレードオフ(または私たちの環境でそれを行う方法)をよく理解していません。

サーバーはBitBucketです(Githubではありません)。私はリポジトリを完全に管理していますが、より一般的にはサーバーにはありません。どれも変更できません。

ソースファイルはXMLです。マージできないことを誰もが知っているグラフィックファイルもありますが、衝突が発生することはほとんどありません。マージの競合は、グラフィックではなくXMLファイルから発生します。

Gitの使用をどのように変更すれば、レビュー済みの、テストで検証されたプルリクエストで機能ブランチを使用できるようになるまで、共有マスターをチームがよりスムーズに進めることができますか?

126
Monica Cellio

これまでのところ、SourceTreeは、概念を学ぶのに最適なIDEでした。これは、各ステージにあるすべての関連ダイアログとオプションが表示されるため、デフォルトのオプションは通常問題なく、リベースをいじる必要はありません。 、など。通常のフローに従ってください。

  • マスターからプルして、最新であることを確認してください
  • ファイルを変更する
  • 変更をコミットします(つまり、ローカルでのみ)
  • マスターから再度プルします(これにより競合が発生します)
  • 競合が解決するまですべてのファイルを編集します。つまり、ファイルはコミットしたい適切な状態になります(未処理ファイルには<<<<<< HEAD and >>>>マスターメッセージはありません)。
  • マージの変更をコミットする
  • 押す

誰もがこのレシピに従えば、大丈夫です。

誰かが大きな変更または中心的な変更を行うたびに、他のユーザーにローカルでコミットしてマスターからプルするように通知します。これにより、後で競合が多くなりすぎず、最初の人が一緒に競合を解決することができます。

全員にフローを理解してもらうために多くの時間を費やしてください。そうしないと、しばらくしてから、実際にマスターブランチをねじ込みながら、慣れてくるでしょう。たとえば、「リモートではなくファイルを使用して」競合を解決します。他の人が行ったすべての変更を除外します。

Gitは習得が難しいシステムです。特にSvnで育った場合は、我慢して、適切に習得する時間を与えてください。新規ユーザーの場合、1日を費やすと混乱することがありますが、これは正常です。 ;)

11
Mike M.

他の人と同じブランチで作業しているときに覚えておかなければならない主なことが3つあります。

  • あなたが本当に自分が何をしているのかを知らない限り、決して--forceを使用しないでください。
  • commitまたはstashのいずれかがpullの前に進行中です。
  • pullの直前にPushを付けると、通常は簡単になります。

それとは別に、分散バージョン管理では、「公式」リポジトリがブランチを使用するかどうかは問題ではないことを指摘しておきます。これは、個々のユーザーがローカルリポジトリで行うことにはまったく関係ありません。私は会社がまったく異なる中央VCSを使用していたときに、gitを使用してローカルブランチを取得していました。彼らが機能のローカルブランチを作成し、ローカルmasterにマージミスをする場合、 reflog やその他の魔法を使わずに修正する方がはるかに簡単です。

98
Karl Bielefeldt

みんながgitを学ぶのに1日かかることは可能ですか?

コンピュータを使用する専門家は、新しいツールを習得することを本当に期待されるべきであり、VCSで多くの間違いを犯す可能性はありますが、使用するように設計されているツールを使用する必要があります。

これを導入する最良の方法は、(可能な限り短く)変更を加えたときに全員が自分のブランチで作業し、リベースしてから、マスターにマージして戻すことです。これは現在の作業方法からそれほど遠くなく、より複雑な操作を実行するのに十分な自信を持つまで、慣れることができる簡単なワークフローを導入します。

私はウィンドウを使用していませんが、Tortoiseが基本的にgitを非表示にし、SVNのふりをしている場合は、Tortoiseが間違ったツールである可能性があります。

67
MarkJL

時々、あなたがやっていることは変わる必要があります。

最大の問題は、全員がマスターに取り組んでいることです。これはコード開発では一般的ではなく、ケースによっては間違ったモデルになる可能性もあります。それを変更できる場合は、その変更を別のブランチで行うように要求/要求することで、より良い状態になります。ブランチを使用すると、以下を取得できます。

  • masterへの直接のプッシュは許可されないことを強制します。
  • プル要求が作成され、マージする前に少なくとも1つの承認がある であることをBitbucketで強制します。これにより、UIはユーザーがデスクトップ上に持っているものではなく、リモートバージョンのコードとの競合を表示するので、誰かが変更を確認し、マージ自体も簡単になります。これにより、コミットは成功したがプッシュは失敗したシナリオが回避されます。
  • マージする前に、リポジトリに対して「ビルド」を実行します。私はそれがドキュメントリポジトリであることを認識していますが、おそらくこのビルドからビルドされる可能性のあるスペルチェック、合法的なスクレイピング、または自動翻訳(STRING_DEFをcsvファイルにエクスポート)さえあります。そうでないかもしれませんが、あなたの仕事に依存します。
  • 人々が複数の異なるものを同時により簡単に作業できるようにします。はい、これはスタッシュで行うこともできますが、少し面倒で、何かを使用していないことを教えてくれます。

分岐を使用するできない場合は、merge-and-Pushいくつかの問題点を自動化できるスクリプト。たぶん、ユーザーがマスターに遅れていないことを確認し、フェッチとプルを行ってから、マージを試みます( おそらく--no-commit --no-ff )など。

26
Dan1701

マージをやり直すことができることを強調する

当たり前かもしれませんが、以前のSVNユーザーは、マージを複数回解決しようとしていることに気付かない場合があります。これにより、受信するヘルプフラグの数を減らすことができます。

SVNでtrunkをオフにすると、コミットされていない変更が発生します。次に、svn updateを実行します。その時点で、あなたの変更は他の人々の変更と永遠に混ざり合うでしょう。元に戻す方法はなかったので(afaik)、手動ですべてを確認して、リポジトリが良好な状態であることを期待するしかありませんでした。実際にマージをやり直すだけではるかに快適になる場合。

私たちがgitに移行しても、人々は同じ考え方を持っているでしょう。多くの意図しないエラーにつながります。

幸いなことに、gitを使用すると、ローカルコミットを作成できるため、元に戻す方法があります。 (コマンドラインでこれがどのように表現されるかについては後で説明します)

ただし、これはツールによって異なります。プルのやり直しは、多くのGUIで単一のボタンとして公開されるものではありませんが、おそらく可能です。私はあなたがcygwinを使うのが好きです。私の同僚はsourcetreeを使用しています。 BitBucketを使用しているため、同じ会社であるAtlassianによって管理されているため、それをGUIとして使用することは理にかなっています。より緊密な統合があると思います。

プルについて

pullでのマージは、人々を混乱させていることだと思います。 pullは実際にはgit fetchで、サーバーから変更を取得し、その後にgit merge Origin/<branchname> *が続き、リモートの変更をローカルブランチにマージします。 ( https://git-scm.com/docs/git-pull

その結果、すべての標準のマージコマンドがプルで機能します。そのマージに競合がある場合は、git merge --abortで中止できます。マージの前に戻るはずです。その後、git pullまたはgit merge Origin/<branchname>を使用して再試行できます。

上記の方法を同僚の選択したGUIツールを使用してどうにか学ぶことができる場合これで問題のほとんどは解決すると思います。申し訳ありませんが、もっと具体的には言えません。

* Originが常にそうであるとは限りません。

git reflogを使用して問題を診断します

私もあなたのように、主にGUIツールの誤用によって引き起こされる問題を診断しなければなりません。 git reflogは、リポジトリでのアクションのかなり一貫した追跡であるため、役立つことがあります。時々読みにくいですが。

代替

あなたの状況はtemporaryなので、ロールアウトするプロセスが整うまでSVNに戻るだけです。多くの場所で「一度gitを試しましたが、うまくいきませんでした...」と言い続け、実際にそれを取り戻すことはないので、私はこれを行うのをためらいます。

その他の一般的な移行上の問題

  • 人々はしばしばリポジトリを削除して再クローンし、リポジトリが使用できない状態にあると確信しました。通常、これはローカルとリモートの違いの追跡を失うことによって引き起こされました。 GUIツールとCLIの両方がこれをうまく表示できません。 CLIでは、違いを概説する最も簡単な方法はgit log --decorateです。しかし、たとえばマスターで物事が毛むくじゃらしたら、git reset --hard Origin/master
12
jmathew

多くのオープンソースチームが採用している1つの可能なメカニズムは、フォークモデルを使用することです https://www.atlassian.com/git/tutorials/comparing-workflows(フォークするgitワークフローについて説明するときは、はっきりと発音してください)

これで、各開発者またはサブチームは、チェックアウトするリポジトリの独自のforkを持っていますこのため、デフォルトのリモートに加えて「アップストリーム」オリジンを設定します。定期的に「アップストリームをフェッチ」し、「リモート/アップストリーム/マスターをマージ」することを覚えておく必要があります。

ビルドツールが別のプロジェクト、つまりフォークのマスターを指す可能性があるため、ビルドメカニズムの問題が解決する可能性があります。

次に、ほとんどの人からマスタープロジェクトに直接プッシュする機能を削除し、レビューと承認の役割を持つ小さなチームのメンバーにすることができます。 https://www.atlassian.com/git/tutorials/making-a-pull-request を参照してください

プッシュの前にほぼすべての望ましいチェックが行われていることを確認する場所は、フックのgit bookセクションにあります- https://git-scm.com/book/gr/v2/Customizing-Git- Git-Hooks -事前コミットおよび事前プッシュフックを使用して、提案されたコミットでいくつかのテストを実行し、作業が有効であることを確認できます。たとえば、クライアント側のフックの唯一の問題は、開発者がそれらを無効にしたり、有効にできない場合があります。

上流のフェッチ/マージとフックの両方がTortoiseGitで利用できます。

8
Steve Barnes

これは直感に反するように聞こえますが、私に聞いてください:

Gitを試してみるように彼らに勧める

Gitの興味深い点の1つは、ローカル操作を完全に安全にすることは驚くほど簡単であることです。私が最初にgitを使い始めたとき、自分がやったことの1つは、ディレクトリ全体を圧縮して、何かが台無しになった場合のバックアップとして使用しました。私は後でこれが巨大なクラッジであり、あなたの仕事を保護するために実際にはほとんど決して必要ではないことを発見しました、しかしそれは非常に安全で非常に優れている単純です。何をしているのか、また、実行したいコマンドがどのようになるのかがわからない場合でも、これを行うときに避ける必要があるのは、Pushだけです。何もプッシュしない場合、これは必要なものをすべて試すための100%安全な方法です。

物事を試すことへの恐怖は、gitを学ぶ上での最大の障害の1つです。それはあなたにsoそれが一種の困難であるすべてのものを多くの制御を与えます。実際には、日常のほとんどの使用において非常に安全な操作をいくつか続けることができますが、それらがどのコマンドであるかを見つけるにはある程度の調査が必要です。

彼らに安全性の感覚を与えることにより、彼らは自分で物事を行う方法を理解しようとすることをはるかに喜んでするでしょう。そして、彼らは彼らのために働く自分のローカルマシン上で個人的なワークフローを見つけるためにはるかに力を与えられるでしょう。そして、全員が同じことをしない場合locally、彼らがPushで標準に準拠している限り、それは問題ありません。操作を行う前にリポジトリ全体を圧縮して、そのように感じさせることができれば問題ありません。彼らは、彼らが行ったり、物事を試みたりしながら、より良いやり方を身につけることができます。 何かを試してみてものを見て、それが何をするかを見てもらうためのもの。

これは、トレーニングに価値がないことを意味するものではありません。それどころか、トレーニングは機能やパターン、規範を紹介するのに役立ちます。しかし、それは座って実際にすることを毎日の仕事で行うことの代わりにはなりません。 gitもSVNも、クラスに行くだけですべてを理解できるものではありません。それらを使用して問題を解決し、問題に慣れ、どの機能がどの問題に適しているかを理解する必要があります。

Gitの詳細を学ぶのをやめさせるのをやめる

私は何もプッシュしないことを述べましたが、これは実際にあなたが教えてきたことの1つ、つまり常に「コミット&プッシュ」に反するものです。私はあなたが彼らにこれをするように言うのをやめ、反対を始めるように彼らに言うべきだと思います。 Gitには基本的に5つの「場所」があり、変更を加えることができます。

  • ディスク上で、コミットされていません
  • 段階的だがコミットされていない
  • localコミットで
  • 地元の隠し場所に
  • リモートリポジトリ(コミットとタグのみが異なるリポジトリ間でプッシュおよびプルされます)

すべてを1つのステップでプルおよびプッシュするように勧めるのではなく、これらの5つの異なる場所を活用するように促します。次のことを奨励します。

  • コミットする前に変更をフェッチします。
  • 取得した変更の処理方法を決定します。オプションは次のとおりです。

    • ローカルの変更をコミットしてから、フェッチした変更の上にそれらをリベースします。
    • ローカルの変更をコミットしてから、取得した変更とマージします。
    • 変更を隠しておき、マージして、競合を解消して解決します。

      他にもありますが、ここでは説明しません。プルは文字通りフェッチとマージにすぎないことに注意してください。それはのようではありません;それはそれらです。 (--rebaseの変更を渡すと、フェッチ+マージからフェッチ+リベースにプルされます。)

  • 変更を段階的に行ってから確認します。
  • 段階的な変更をコミットしてから、コミットを確認します。
  • 個別に押します。

これにより、すべての人に公開される前にbeforeの作業を確認することができます。つまり、間違いをすぐに見つけられるようになります。彼らはコミットを見て、「待って、それは私が欲しかったものではない」と考え、SVNとは異なり、戻ることができ、プッシュする前にもう一度試すことができます。

変更がどこにあるかの理解に慣れると、ステップをスキップして特定の操作を組み合わせるタイミング(フェッチするタイミングがわかっているため、プルするタイミング)の決定を開始できます。 +マージまたはそのコミットとプッシュオプションをクリックするタイミング)。

これは実際にはSVNよりもgitの大きな利点の1つであり、gitはこの使用パターンを念頭に置いて設計されています。対照的に、SVNは中央リポジトリーを想定しているため、gitのツールが同じワークフロー用に最適化されていなくても、当然のことです。 SVNでは、コミットが間違っている場合、間違いを取り消すための新しいコミットが唯一の手段となります。

これを行うと、実際には次の戦略に自然につながります。

localブランチを使用するように彼らを励ます

ローカルブランチは実際に共有ファイルで作業する際の多くの問題点を緩和します。私は自分のブランチで必要なすべての変更を行うことができます。プッシュしないので、誰にも影響を与えることはありません。その後、その時が来れば、同じマージとリベースの戦略をすべて使用できますが、それは簡単です。

  • ローカルブランチをリベースすることができるので、マスターを簡単にマージできます。
  • Masterでプレーンマージ(新しいコミットを作成)を使用して、ローカルブランチの変更をそこに取り込むことができます。
  • 私のブランチが混乱しすぎて救出できないと思った場合、ローカルブランチ全体をマスター上の1つのコミットにスカッシュマージできます。

ローカルのブランチを使用することも、体系的なブランチ戦略を理解するための良いスタートです。これは、ユーザーが自身のブランチングのニーズをよりよく理解するのに役立ちます。そのため、ニーズとチームの現在の理解度/スキルレベルに基づいて戦略を選択でき、Gitflowだけでなく、誰もがそれを聞いているためです。

概要

つまり、gitはSVNではなく、そのように扱うことはできません。必要がある:

  • 安全な実験を奨励することによって恐怖を排除します。
  • Gitの違いを理解してもらい、通常のワークフローがどのように変化するかを理解してもらいます。
  • 問題をより簡単に解決するために利用できる機能を理解してもらいます。

これにより、一連の標準の実装を開始できるようになるまで、徐々に徐々により良いgitの使用法を採用できます。

特定の機能

当面は、次のアイデアが役立つかもしれません。

リベース

あなたはリベースについて言及しましたが、質問ではそれを本当に理解していません。だからここに私のアドバイスです:私が今説明したことを試してみてください。他の誰かがいくつかの変更をプッシュしている間に、ローカルでいくつかの変更を行います。変更をコミットしますlocally。バックアップとしてリポジトリディレクトリを圧縮します。他の人の変更を取得します。ここでrebaseコマンドを実行して、コミットがどうなるかを確認してください!無限のブログ投稿を読んだり、リベースや、それをどのように使用するべきか、または使用しないべきかについてのトレーニングを受けたりできますが、それが実際に動作しているのを見ることの代わりになるものはありません。 それを試してみてください

merge.ff=only

これは個人的な好みの問題になりますが、競合の処理にすでに問題があるとおっしゃっていたので、少なくとも一時的にお勧めします。 setting merge.ff to only をお勧めします:

git config --global merge.ff only

「ff」は「早送り」の略です。早送りマージは、gitが異なるコミットからの変更を組み合わせる必要がない場合です。グラフの直線に沿って、ブランチのポインタを新しいコミットに移動するだけです。

これが実際に行うことは、gitがマージコミットを自動的に作成しようとするのを防ぐことです。したがって、ローカルで何かをコミットし、他の誰かの変更をプルする場合、マージコミットを作成しようとするのではなく(そして、ユーザーに競合の処理を強制する可能性があります)、マージは失敗します。実際、gitはfetchのみを実行します。ローカルコミットがない場合、マージは通常どおり続行されます。

これにより、ユーザーは、さまざまなコミットをマージする前にそれらを確認し、それらの結合を最適に処理する方法について決定を強制することができます。リベースしたり、マージを続行したり(git merge --no-ffを使用して構成をバイパスする)したり、変更のマージを今のところ延期して後で処理することもできます。この小さな速度のバンプは、チームがマージについて誤った決定をするのを防ぐのに役立つと思います。マージの処理が上手くなったら、チームにオフにさせることができます。

3
jpmc26

私は会社でまったく同じSVN-> gitエクスペリエンスを経験しました。私の経験から、唯一の救済策は時間です。ツールに慣れさせ、間違いを犯させ、修正方法を示しましょう。あなたの速度はしばらくの間苦しみ、人々は仕事を失い、そして誰もが少し悲惨になりますが、それはあなたのVCSと同じくらい根本的な何かを変える性質です。

とは言っても、移行期間の早い段階でTortoiseGitがヘルプではなく妨げであるという意見のある人はすべて同意します。 TortoiseGitは...最良の状態では優れたGUIではありません。また、単純さの名の下にgitが実際にどのように機能するかを不明瞭にすることで、2フェーズコミットなどのgitのコアコンセプトを同僚が理解することも妨げています。

開発者にコマンドライン(git bashまたは posh-git )を1週間使用するよう強制する(かなり抜本的な)決定を行いました。これは、gitが実際にどのように動作し、どのように動作するかを理解するのに不思議に働きましたSVNとは異なります。極端に聞こえるかもしれませんが、gitモデルの理解が深まるという理由だけで試してみることをお勧めします。それが下がると、同僚はgitよりもGUIファサードを好きなように使用できるようになります。

最後の注意:gitがどのように機能するかをすぐに理解している同僚もいれば、そうしない同僚もいるでしょう。後者のグループでは、誰もがそれを見ることができるように、コードをローカルマシンからサーバーに取得するように神秘的な呪文を教える必要があります。

2
Ian Kemp

さて、最近私は次のワークフローを適合させて、masterブランチを決してf * ckしません:

1)全員が独自のブランチを使用します。これは、最初はマスターブランチからのコピーです。

マスターブランチに「master」、自分のブランチに「my_master」という名前を付けましょう。

私はマスターからブランチを作ったばかりなので、まったく同じです。私は自分のブランチで新しい機能の作業を開始し、完了したら次のことを行います。

私のブランチのカレンリー、ちょうどコーディングを終えた

git add . && git commit -m "Message" && git Push

Masterブランチに戻る

git checkout master

最新でない場合はプルする

git pull

自分のブランチに戻る

git checkout my_master

最新のマスターを自分のブランチにマージします

git merge master

競合とマージを修正する

すべてをもう一度テストする

すべてがマージされて自分のブランチで修正されたら、それをプッシュします

git Push

Masterブランチに戻る

git checkout master

私のブランチとマージ

git merge my_master

以前のマージで自分のブランチで解決されるため、競合が発生する可能性はありません

プッシュマスター

git Push

誰もがこれに従えば、マスターブランチはクリーンになります。

1
TanguyB

したがって、TFSからgitに切り替えて、古い考え方を維持したチームがいます。一般的な操作規則はほぼ同じです。

はい、これは誰もがマスターで作業することを意味します。これはそれほど悪くはありません。そして、TFSまたはSVNに慣れているチームは、これが最も自然であるとわかります。

これを可能な限り簡単にするための一般的な手順:

  1. 行う git stash && git pull --rebase && git stash pop毎朝
  2. 早い段階で頻繁にコミットする(すぐにプッシュする必要はありません。少なくともgitのこの利点を早期に利用することができます)
  3. プッシュするには、次のループを実行します。

    git add git commit git pull --rebase fix any merges compile git Push loop until you don't get the can't fast forward error message.

0
Joshua