МЕРЗАВЕЦ: Добавление патча, сделанного после нескольких фиксаций

Интересный, сколько сравнений в образце MSDN...

public static double Median(this IEnumerable<double> source) {
        if (source.Count() == 0)  throw new InvalidOperationException("Cannot compute median for an empty set.");

        var sortedList = from number in source
                         orderby number
                         select number;

        int itemIndex = (int)sortedList.Count() / 2;

        if (sortedList.Count() % 2 == 0) {
            // Even number of items.
            return (sortedList.ElementAt(itemIndex) + sortedList.ElementAt(itemIndex - 1)) / 2; } else {
            // Odd number of items.
            return sortedList.ElementAt(itemIndex); }
    }
8
задан David Dombrowsky 9 October 2009 в 19:12
поделиться

2 ответа

Что случилось

Вы имеете в виду поправить, а не добавить, верно? Для удобства я сделаю вид, что это было в ветке под названием master. Вот как теперь выглядит ваш репозиторий:

A---B' (master)
 \
  \-B---C---D

Коммиты Git явно зависят от их родителей - тот же патч поверх другого родителя - это другой коммит.

Как восстановить

Вы можете восстановить предыдущую позицию несколькими способами. Есть удобное сокращение для предыдущих позиций, которое вы можете использовать, чтобы напрямую проверить это или создать ветку:

git checkout master@{1}
git branch oldmaster master@{1}

Предполагается, что это первая предыдущая позиция. Это может быть второй ( master @ {2} ) ... или, если вы знаете, когда это было, вы можете использовать master @ {7:35} или master @{23.hours.ago}. For a summary of these forms, see the "specifying revisions" section of man git-rev-parse (online here).

If you're not sure exactly how to get to it, try

git reflog show master

This will give you a list of previous positions of master, and you should be able to tell from the descriptions which one you want (or maybe try a few). You can simply copy hashes from the list, and use git checkout or git branch as above.

What you should have done

Warning: editing history is a bad idea if it's been published already - in that case, you should simply commit the fix. Yes, it's kind of ugly having it split into two commits in the repository, but other users have to be able to trust what they've seen in the public repo not to change!

That said, to do this particular kind of history editing, you want interactive rebase:

git rebase -i master~4 master

master~4 represents the commit four commits before the tip of master. You can use any form you want here - maybe it's another branch, maybe a commit hash - whatever works.

This will open up in an editor a list of the commits you're playing with:

pick <hash-A>  <message-A>
pick <hash-B>  <message-B>
pick <hash-C>  <message-C>
pick <hash-D>  <message-D>

# Rebase <hash-A^>..<hash-D> onto <hash-A^>
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

The commented-out help text there is pretty self-explanatory. In this case, you want to change 'pick' to 'edit' on commit B's line, save, and quit. The rebase will start, and it'll pause after applying B to let you make changes. You'll do what you need to, add, use git commit --amend, and then git rebase --continue. It'll apply C and D, and you'll be done. If anything goes wrong in the middle, use git rebase --abort to get back to where you started.

Rebasing can be kind of scary - for example, don't accidentally remove lines in that list! If you're not comfortable with it yet, it's a good idea to make heavy use of gitk and backup branch names.

14
ответ дан 5 December 2019 в 11:26
поделиться

4) to my surprise, the tree now reads

A--B

Actually the log (the history) looks like this

A--B'

as the commit is different than before. The situation looks like the following:

A---B'                         <-- master  <--- HEAD
  \
    \--B---C---D

The chain of commits "B---C---D" (with original B) looks lost, because there is no reference pointing to D. Your branch now points to commit B' (modified commit B). You can still access D via reflog; it would be HEAD@{2} I think...

Where did I go wrong?

You should have used "git rebase --interactive", changing 'pick' beside commit B to 'edit', and squash a patch there.

That, or use one of patch management interfaces on top of Git like StGIT or Guilt.

Their details are gone from the logs and I don't think I can get them back.

Take a look at reflog, i.e. "git reflog", or "git log -g". There you should see your "lost" commits.

HTH

1
ответ дан 5 December 2019 в 11:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: