19566


GitHubのログがあまりにも汚くて困っております。このブランチ名を横一列にキレイに並べる方法はどうすればいいのでしょうか？コミットグラフが枝分かれしないようにしたいと考えています。  
staging でテストして結果が問題なければmasterに上げるようにしています。今のところソースコード自体にstaging
とmasterに違いはありません。  
現在の状態はこのようになっております。

[code]

    $ git graph
    *   7e3b98e      (HEAD, origin/master, origin/HEAD, master) Merge branch 'staging'
    |\
    | * 6151ba5      (origin/staging, staging) Fix purchased job
    | *   dcf83c1    Merge branch 'staging' of github.com:KlujePteLtd/kluje into staging
    | |\
    | | * b1e059a    Hide section testimonials
    | | * a1e6763    Fix initializers/carrierwave
    * | |   c5a607a  Merge branch 'staging'
    |\ \ \
    | |/ /
    | * | a4bf0ea    Fix initializers/carrierwave
    
[/code]

以前まではgit rebaseを使って以下のように横一列にしておりました。履歴は全て一直線（時に分かれても２つまで）でした。

[code]

    $ git graph
    * 8da8fde        (HEAD, origin/HEAD, origin/master, origin/staging, master, staging ) Add find_matches test
    * 8b1aa58        Fix inviter Serializer
    * 0c6daa1        Add venue invitation
    * 7bd9478        Add byebug rails-erd gems
    * d03ab72        Add find_matches test into RSpec User Model
    * 928032a        Add positive_sort into User Model
    
[/code]

どこかのタイミングで混沌とした状況になり、それ以降はgit rebaseを使ってもまったくキレイにならなくなり  
手をかければかけるほど汚くなっていきます。

基本的なGit作業はこのようにしておりました。

[code]

    $git branch
    > staging
    $git push origin staging
    （staging環境にて動作確認）
    $git fetch
    $git rebase origin/master
    $git checkout master
    $git merge staging
    $git push origin master
    
[/code]

どうすればいいのでしょうか？

> 回答を元に作業を繰り返した結果
[code]

    * c88832e        (HEAD, origin/master, origin/HEAD, staging, master) The last change
    *   7e3b98e      Merge branch 'staging'
    |\
    * \   c5a607a    Merge branch 'staging'
    |\ \
    * | | c0c4d7e    Fix initializers/carrierwave
    | | | * 48f91d5  (origin/staging) The last change
    | | |/
    
[/code]

unaristさんの回答とリンク先のスライドなどを何度も読み返すのですが、どうしてこんな結果になってしまうのかどうしてもよく分からないです。何度も申し訳ないのですが、なんとか解決方法を教えていただけないでしょうか？

この状態で

[code]

    $ git push origin staging
    
[/code]

をすると

[code]

    ! [rejected]        staging -> staging (non-fast-forward)
    
[/code]

の警告が出ます。


CC BY-SA 3.0
2015-12-02T09:53:44.623
19553
2015-12-03T03:22:00.840
2015-12-02T16:09:21.047
9202
9202
question
git github
GitHubのログにあるmaster, origin/master, staging, origin/staging を横一列にキレイに並べる方法


コミットグラフを一直線に保つ、つまりマージコミットを作成しないためには、コミット上「分岐した後で合流する」ことを避けなければいけません。これは別のブランチのコミットを取り込む時（staging→masterなど）だけでなく、
**同じブランチに他人がpushしたコミットを取り込む時** にも注意が必要です。

  1. origin/staging にpushする
  2. 別の人が origin/staging にpushする
  3. staging にコミットを追加する
  4. origin/staging にpush・・・できない

そこであなたは fetch
をされているようですが、fetchはリモートリポジトリのブランチ情報を手元（例えばorigin/staging）に持ってくるだけで、ローカルブランチ（staging）は更新しません。このままstagingをpushした場合、fetchした意味は全くありません。

対応するリモートブランチのコミットをローカルブランチに取り込む際には一般に `git pull`
というコマンドが使われますが、内部的にはfetchしてmergeするということを行っています。一直線にするにはmergeではなくrebaseを使わないといけないので、
`--rebase` オプションを使うとよいでしょう。

> それ以降はgit rebaseを使ってもまったくキレイにならなくなり  
>  手をかければかけるほど汚くなっていきます。

mergeにせよrebaseにせよ、パラメータとして指定した相手ブランチはそのままの位置を保ちます。そのため、`7e3b98e`でmasterにstagingをmergeしていますが、stagingは`6151ba5`のままです。このままstagingにコミットしていくと
`7e3b98e` が含まれないままですから、やはり分岐してしまいます。

masterの末尾にある `7e3b98e`
がstagingにも含まれるようにすればいいので、つまりmergeですね。ただし、質問の状態からstagingにコミットが増えているなら、rebaseする必要があります。

[code]

    git checkout staging
    git rebase master
    
[/code]

`--ff-only` はマージコミットの発生する non fast-forward merge
をエラーにするオプションです。安全策として付けておくと安心かもしれません。

ところで、masterに直接コミットすることがないのであれば、stagingは常にmasterのコミットを全て含んでいるはずですから、stagingからmasterへのrebaseは必要ないはずです。

まとめると、今後は以下のような手順になるかと思います。

[code]

    $ git branch
    > staging
    $ git pull --rebase （もしorigin/stagingが更新されていればrebase）
    $ git push origin staging
    （staging環境にて動作確認）
    $ git checkout master
    $ git merge --ff-only staging
    $ git push origin master
    
[/code]

参考

  * [こわくない Git](http://www.slideshare.net/kotas/git-15276118) （mergeやrebaseの説明、rebaseの注意点など。ぜひご一読ください）
  * [ブランチの統合【ブランチ】 | サルでもわかるGit入門 〜バージョン管理を使いこなそう〜](http://www.backlog.jp/git-guide/stepup/stepup1_4.html)
  * [中央管理型ワークフロー | アトラシアン Git チュートリアル](https://www.atlassian.com/ja/git/workflows#!workflow-centralized)

* * *

あなたが手元のstagingにコミットした `c0c4d7e` をorigin/stagingにpushする前に他の方が `48f91d5`
をpushしてしまったようですね。じゃあstagingをorigin/stagingにrebase・・・といきたいところですが、`c0c4d7e`
は既にorigin/masterにpushしてしまっているので、rebaseすべきではありません。

目標はmasterの先にstagingがある状態なので、masterと、独立してしまったお手元のstagingをorigin/stagingにmergeしましょう。

  1. 最新のorigin/stagingをfetchしてくる
  2. origin/staging上でstagingをmerge
  3. 続けてmasterをmerge （これは `Already up-to-date!` になるかもしれませんが）
  4. その場でstagingブランチを作り直す  
これは `git checkout -B staging` を使うとよいでしょう。 `-b`
は現在のコミットにブランチを作成するオプションとして知られていますが、`-B` にすると既存のブランチの変更が行えます。

  5. stagingをpush

という作業を、 **他の方がorigin/stagingを触っていない間に** 行ってください。

余談ですが、一直線のブランチを維持するためには、「non fast-forward
mergeをしない」「pushする前に最新のorigin/**に対してrebaseする」ことをチームメンバー全員で守る必要がありますが、守ってくれない人がいたりrebaseが面倒になったりで、私はフィーチャーブランチを使った作業フローに切り替えました。


CC BY-SA 3.0
2015-12-02T13:58:05.933
19566
2015-12-03T03:22:00.840
2015-12-03T03:22:00.840
8000
8000
19553
answer