2010-02-18 3 views
4

Это как gitk в настоящее время выглядит в одном из наших проектов:Странный мерзавец слияние вопрос

https://dl.dropbox.com/u/2582508/gitk.png

Это, по-видимому, от всех мы можем сказать, произошло после того, как один «мерзавец слияние» было сделано с пульта дистанционного управления ветка - мы не знаем, почему и что происходит. Любая идея, что здесь произошло?

Что еще более важно, что это лучший способ исправить это? Эти коммиты слияния пустые, но при выполнении «git rebase -i» комманды слияния обычно не отображаются.

Самое главное, я бы предпочел, чтобы история не была несовместима с другими клонами, то есть они все равно могли тянуть/толкать/сливаться с ней. Возможно ли это?

+0

Я бы просто отказался от этого клона и клонировал еще одну копию. У вас есть какие-либо «не поддерживаемые ветви/коммиты» в этом клоне? –

+0

Вы делитесь через центральный репозиторий (т. Е. Все ли вы нажимаете и вытаскиваете из общего репозитория)? –

+0

Да, есть общий репозиторий, и там уже проделана дальнейшая работа. – miracle2k

ответ

3

Это результат того, что кто-то обновляет свой проект, используя git pull (или, что то же самое, git fetch и git merge). Представьте, что вы выглядите репозитории так:

 
o---o---o [origin/master] 
     \ 
      A---B---C [master] 

То есть, вы сделали совершает A, B и C на вершине того, что было в первоначальном репо.

Между тем, некоторые другие вносят изменения и выталкивают их в общий репозиторий. Если затем запустить git fetch ваше хранилище выглядит следующим образом:

 
o---o---o---D---E---F [origin/master] 
     \ 
      A---B---C [master] 

Теперь, если вы запустите git merge (помните: git pull только git fetch следует git merge). Вы будете иметь это:

 
o---o---o---D---E---F [origin/master] 
     \   \ 
      A---B---C---G [master] 

Предполагая, что все идет хорошо, G, вероятно, просто «тупо» сливаться совершить; технически, состояние G отличается от F и C, и поэтому его следует рассматривать по-разному.

Теперь, если нажать это изменение, вы будете иметь это:

 
o---o---o---D---E---F 
     \   \ 
      A---B---C---G [origin/master] 

И если вы будете продолжать развитие, вы получите это:

 
o---o---o---D---E---F 
     \   \ 
      A---B---C---G [origin/master] 
         \ 
         H---I---J [master] 

Теперь, если вы продолжаете делать это (и если многие люди продолжат это делать), вы получите дерево, подобное тому, что показано на картинке. Это не «неправильно», но многим людям это не нравится, потому что очень сложно следить за развитием истории.

Решение этой проблемы - научить людей переустанавливать. Rebasing будет (как вы отметили) удалять бесполезное слияние, и вы получите гораздо более чистую историю. В приведенном выше случае вы получите линейную историю развития. Это намного легче следовать. Однако вам нужно знать, что после переустановки вам необходимо перестроить и повторно протестировать свой код ... просто потому, что код легко сливается, это не значит, что результат правильный.

Если вы используете центральный репозиторий для обмена официальной линией разработки, вы можете реализовать крюк предварительного приема, который обнаруживает эти автоматические («глупые»/«бесполезные») слияния, и отклоняет push-принудительное пользователя для переустановки. На самом деле, вы хотите, чтобы крючок искал сообщение об ошибке слияния по умолчанию ...поэтому, если вы действительно хотите сохранить фиксацию слияния (иногда это имеет смысл), вы должны хотя бы написать сообщение интеллектуального фиксации.

Вот пример крючка. Я удалил кучу лишних вещей, поэтому я не смог его проверить.

 
#!/bin/bash 

# This script is based on Gnome's pre-receive-check-policy hook. 
# This script *only* checks for extraneous merge commits. 

# Used in some of the messages 
server=git.wherever.com 

GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) 

in_import() { 
    test -e "$GIT_DIR/pending" 
} 

forced() { 
    test -n "$GNOME_GIT_FORCE" 
} 

check_commit() { 
    commit=$1 

    subject="$(git log $commit -1 --pretty=format:%s)" 
    if expr "$subject" : ".*Merge branch.*of.*\(git\|ssh\):" > /dev/null 2>&1; then 
      if ! in_import && ! forced ; then 
       cat &2 
--- 
The commit: 

EOF 
     git log $commit -1 >&2 
     cat &2 

Looks like it was produced by typing 'git pull' without the --rebase 
option when you had local changes. Running 'git pull --rebase' now 
will fix the problem. Then please try, 'git push' again. Please see: 

    http://live.gnome.org/Git/Help/ExtraMergeCommits 
--- 
EOF 
     exit 1 
      fi 
    fi 
} 

check_ref_update() { 
    oldrev=$1 
    newrev=$2 
    refname=$3 

    change_type=update 
    if expr $oldrev : "^0\+$" > /dev/null 2>&1; then 
    change_type=create 
    fi 

    if expr $newrev : "^0\+$" > /dev/null 2>&1; then 
      if [ x$change_type = xcreate ] ; then 
      # Deleting an invalid ref, allow 
       return 0 
      fi 
      change_type=delete 
    fi 

    case $refname in 
    refs/heads/*) 
     # Branch update 
     branchname=${refname#refs/heads/} 

     range= 
     # For new commits introduced with this branch update, we want to 
     # run some checks to catch common mistakes. 
     # 
     # Expression here is same as in post-receive-notify-cia; we take 
     # all the branches in the repo, as "^/ref/heads/branchname", other 
     # than the branch we are actualy committing to, and exclude commits 
     # already on those branches from the list of commits between 
     # $oldrev and $newrev. 

     if [ -n "$range" ] ; then 
     for merged in $(git rev-parse --symbolic-full-name --not --branches | \ 
        egrep -v "^\^$refname$" | \ 
      git rev-list --reverse --stdin "$range"); do 
      check_commit $merged 
     done 
     fi 
     ;; 
    esac 

    return 0 
} 

if [ $# = 3 ] ; then 
    check_ref_update [email protected] 
else 
    while read oldrev newrev refname; do 
    check_ref_update $oldrev $newrev $refname 
    done 
fi 

exit 0 
+0

Спасибо за ваш ответ. Тем не менее, я либо не понимаю этого, либо я не был ясен в своем вопросе. Я понимаю, что комманды слияния, и я в порядке, чтобы они были в центральном репо - я не думаю, что мы хотим использовать rebase здесь. Но на скриншоте выше у меня есть что-л. как 30 последующих слияний, каждый с двумя родителями: прямое предыдущее слияние и одно в серии старших коммитов. Не было 30 шагов разработки-слияния. И хотя мне трудно понять эти деревья, слияния также кажутся мне ненужными. Один (или несколько) мог бы выполнить цель, которую вы описываете. – miracle2k

Смежные вопросы