m_nakai
@m_nakai

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Git運用についての質問です

Gitで「行」単位ではなく「ファイル」単位でコンフリクトを起こさせる方法はありませんでしょうか?

また、その方法がない場合要件に対するアイデアありませんでしょうか・・

Gitの運用方法を模索しておりますが、少し特殊な要件があるため質問させていただきました。
ぜひアイデアなどありましたらご意見いただければ大変助かります。

■想定している運用ブランチ

master
∟feature_1
∟feature_2
∟feature_X..

(masterとfeatureブランチの2ブランチを考えており、featureブランチではそれぞれの人が割り振られて改修内容を対応しております)

■要件

①featureブランチではブランチを作成したタイミングから最終的に自分が作業した分の差分を出力する要件があるため「プル」ができない

→ブランチを作成したタイミングから最終コミットまでのコミット間で差分を出力したいです。
 プルすると他人のブランチの作業分(すでに改修が終わってmasterブランチにマージされたもの)が差分として出力されてしまうため「プル」ができないと思っています。
→プルしても自分の作業分だけこうやったら出力できるよ、などあれば教えていただきたいです。

② Gitで「行」単位ではなく「ファイル」単位でコンフリクトを引き起こしたい

→①で改修した差分データをサーバーへアップしておりますが、稀に共通ファイルをそれぞれのfeatureブランチで触ってしまっていることがあります。その際、後方に上げたブランチ内容がサーバーにアップされた際に
先祖帰りしてしまう現象が起こってしまっています。ですのでサーバーに上げる前にコンフリクトか何かでわかりたいのですが共通ファイルの同じ行を触っていればコンフリクトとしてマージタイミングで気付けるのですが違う行を触っている場合はGitの通常動作通りマージされてしまい気付くことができません。
何か方法があるのでしょうか。調べても出てこないためご意見いただければ幸いです。
 

0

7Answer

プルすると他人のブランチの作業分(すでに改修が終わってmasterブランチにマージされたもの)が差分として出力されてしまうため「プル」ができないと思っています。

ブランチ単位でpullはできます.

その際、後方に上げたブランチ内容がサーバーにアップされた際に
先祖帰りしてしまう現象が起こってしまっています。
ですのでサーバーに上げる前にコンフリクトか何かでわかりたいのですが共通ファイルの同じ行を触っていればコンフリクトとしてマージタイミングで気付けるのですが違う行を触っている場合はGitの通常動作通りマージされてしまい気付くことができません。

ここちょっと目的がよく分からないのですが,文章から察するにfeatureブランチの1コミット内容が大きすぎるわりにmasterへのマージが少々頻繁なのではないかと思われます.

そのような場合,例えば前コミットの1ファイルに問題があることがわかった段階で,そのコミットで他の大部分のソースも変えていたためにいちいちcherry pickしなければならない…というときに困ります.
featureではビルドや依存関係が通る等,細かく作業単位を決めて積極的にコミットしてもよいのでは?

複数人プロジェクトでのGit開発手法としては,

  1. 細かい回収作業をfeatureブランチにコミットとして積み重ねる
  2. 動作確認等ができたらPull Requestを作成する
  3. レビュー等の上masterにマージ

という流れになると思います.

PRはGitHubやAzure Devops等有名どころならだいたい使えますので活用してください.

2Like

他人のコード(feature1)がmasterにマージされた時点なら、二番手以降の人(例えばfeature2)はrebaseあるいはmerge(master>feature2)を利用して最新のコードにしてからmasterにマージするべきです。

同時にマージされることはないので、先祖返りを起こさないようにテストするのは二番目以降の人の責務です。

そして、コンフリクトが発生するとそのような手間が発生するので、先に指摘されているようにブランチに含める内容を減らしたり、範囲を明確にすることをおすすめします。
ビルドしたバイナリファイルがバージョン管理されていてどこをいじっても衝突する、みたいな場合はコミットに含めるものが間違っている可能性もあります。

1Like

Comments

  1. @m_nakai

    Questioner

    >最新のコードにしてからmasterにマージするべき

    おっしゃる通りmergeやプルして最新化するべきなのですが、

    featureブランチでの変更差分「だけ」納品する必要がありまして
    他ブランチで動いている変更内容をプルしてしまうと
    コミット間差分出力で他ブランチの差分データも納品データに入ってきてしまうので
    そのご指摘ができない運用でありました。
  2. なぜ最終的に混ぜるコードについて個別の修正を要求されている(かつそれらはコンフリクトするような密なファイルについて)のかは謎で仕方ないですね、、、作業内容という意味なら一つ前のマージコミットから自分のブランチのdiffがそれであるはずなのですが、、、GITからSVNに先祖返りしたような要求に思います。


    その作業要件なら先祖返りを起こしているだろう最後の全マージの時に、一個づつレビューするしか無さそうですね。
    f1 into master = master' これは問題ないはず
    f2 into master' ここで問題が起きる
    ので
    master' into f2 = f2' でマージしてコンフリクト直してテストする
    f2' into master' = master'' 以下同様

    のように納品後に敗戦処理をしないと行けない気配がします。
  3. マージまでを自社でしなければならないなら、最新コード(継ぎ足し状態)にすることは全ての機能を実装するのに必要不可欠であることを説明しなければならないと思います。

    いや別に差分さえ分かればいいんだよその後は知らないと、という話なら納品後に納品先が解決した謎のマージ結果をただ受け取るのが正解な気がします、、、

→ブランチを作成したタイミングから最終コミットまでのコミット間で差分を出力したいです。
→プルしても自分の作業分だけこうやったら出力できるよ、などあれば教えていただきたいです。

git diff master...feature_X

でできます。

1Like

ようやくやりたいことがわかりました。コンフリクトを起こしたいなど書かず、変更ファイルの一覧を知りたいと書いてくれれば即答でした。

git diff --name-only feature...master

で変更ファイル名一覧がでます。当然、同じ操作をしているブランチがあればそららのブランチで同じファイル名が出ますので、ブランチを切り替えてデプロイしたときに未反映が発生します。

目視で確認でも、更にコマンド処理するでも好きにしてください。コマンドなら以下みたいな、、、?

git diff --name-only feature1...master >> files.txt
git diff --name-only feature2...master >> files.txt
sort files.txt | uniq
1Like

Comments

  1. でも、内部的にマージしたブランチでデプロイやテストを行い、納品だけ別ブランチで作業内容を伝えるのがよいのではゴニョゴニョとも思います

    つまり、masterからfeatureを切る、feature からdevelopにマージする、全混ぜdevelopでテストする、納品はfeatureでする、納品後はdevelopをmasterに混ぜる
  2. @m_nakai

    Questioner

    ありがとうございます!
    運用にdiffで少し取り入れて考えてみようと思います!

共通ファイルをそれぞれのfeatureブランチで触ってしまっていることがあります。その際、後方に上げたブランチ内容がサーバーにアップされた際に先祖帰りしてしまう現象が起こってしまっています

ふつうにやれば先祖返りはしません。

feature_1とfeature_2で同じファイル内の別々の位置を修正(コンフリクトしない修正)をしていた場合、
masterブランチへfeature_1をマージし、
その後masterブランチへfeature_2をマージすれば、
masterブランチのそのファイルは両方の修正が入った状態になります。

どういう操作をしたとき先祖返りするのか具体例を上げてもらえば、適切な助言ができるかもしれません。

0Like

Comments

  1. @m_nakai

    Questioner

    ご意見ありがとうございます!

    条件として提示している通りプルできない上、
    masterブランチへマージする「前」に
    featureブランチ上で差分データを出力し納品する要件があったので
    別ブランチで動いている共通データを触っていた際に先祖帰りしてしまっておりました..

    普通だとmasterブランチへマージした後
    masterブランチで納品データ作るor masterとfeatureをプルなどで同期した上で
    納品データを作るのがセオリーだとは思いますが、、

違う行を触っている場合はGitの通常動作通りマージされてしまい気付くことができません。

その場合は触った方(=新しい方)が残されるようにマージされるので、先祖返りにはなりません。
先祖返りが起こっている理由を把握しないまま対処しようとするのはさらに混乱を招く可能性が少なくないです。

プルすると他人のブランチの作業分(すでに改修が終わってmasterブランチにマージされたもの)が差分として出力されてしまうため「プル」ができないと思っています。

最新のmasterブランチをプルして作業中のfeatureブランチにマージすると、作業中のfeatureにとっては余計な差分が増えたように見えますが、それをmasterブランチにマージするときにはmasterの内容と同じなので差分扱いはされません。

あと

featureブランチではそれぞれの人が割り振られて改修内容を対応しております

これは「タスクごとにfeatureブランチを作り、そのブランチごとに担当を割り振る」または「担当者ごとにfeatureブランチが割り振られ、担当者が同じ複数のタスクをひとつのブランチで処理している」のどちらの意味でしょうか。後者はあまりよくないやり方だと思います。
ブランチが担当者単位に分かれていると、複数の変更をまとめてコミット/プッシュしてしまうことが多くなり、その結果一つのコミットに多くの変更が含まれるため、その一部に問題があるとcherry pickを強いられます。
一つのブランチ内に多くの変更があれば、それだけ最新のmasterをプルしてマージするのも煩わしくなります。これが先祖返りを起こす最大の要因かもしれません。

ブランチは担当者単位ではなくやろうとするタスク単位で分けた方がいいです。
そのブランチをmasterにマージしてタスクが完了したらそのブランチは削除します。
ブランチを削除しても、そのブランチの履歴はマージしたmasterに残っているので削除しても大丈夫です。

特に共通ファイルに手を加える場合は、手を加える理由となる元のタスクとは別に「共通ファイルの○○を変更するブランチ」などを作った方がいいです。
そうすることで「ファイル単位のコンフリクト」(たぶんコンフリクト解消の具体的な手順はあまりまとまっていないでしょう)よりずっと管理しやすくなると思います。

0Like

Comments

  1. @m_nakai

    Questioner

    通常のコミットとは違う方法でしょうか?

Your answer might help someone💌