Подтвердить что ты не робот

Автоматически сохранить изменения/всплывающие изменения на git rebase?

Мой рабочий процесс git использует rebase много. Я всегда получаю изменения вверх по течению (основное репо, из которого я разветвлен), а затем сливаюсь с моими ветвями, а затем переустанавливаю, чтобы удалить бесполезные (ко мне: D) слияние коммитов и древовидные разбиения.

одна вещь в этом рабочем процессе меня раздражает:

$ git rebase upstream/master
Cannot rebase: You have unstaged changes.
Please commit or stash them.

$ git stash
Saved working directory and index state WIP on cc: abc1234 Merge remote-tracking branch 'upstream/master' into local_branch
HEAD is now at abc1234 Merge remote-tracking branch 'upstream/master' into local_branch

$ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Applying: awesome code change

$ git stash pop

так что здесь у нас есть 4 команды, 1 = неудачная перезагрузка, 2 = stash, 3 = rebase, 4 = popash pop. ничего, кроме 3 - просто бессмысленная работа.

Итак, возникает вопрос: какой самый рекомендуемый способ его автоматизации? псевдоним для запуска git stash/rebase/pop everytime? некоторая конфигурация git, которая заставляет rebase ставить или рассматривать ее как другую фиксацию для повторного применения после этого? что-то еще?

4b9b3361

Ответ 1

Изменить: Начиная с версии Git версии 1.8.4, но с важной боковой ошибкой, зафиксированной в Git версии 2.0.1, git rebase теперь имеет --autostash. Вы можете настроить git rebase на использование --autostash по умолчанию, используя git config --global rebase.autoStash true. Обратите внимание на следующее предложение документации:

Однако, используйте с осторожностью: последний тайник  приложение после успешной перезагрузки может привести к нетривиальному  конфликты.

(Я по-прежнему предпочитаю делать коммиты.)

TL; DR ответ: просто сделайте фиксацию (затем снимите ее позже)

Это может помочь вам понять, что git stash на самом деле просто git commit (в более сложной форме, которая сначала фиксирует индекс, а затем - дерево работы - при применении кошелька вы можете поддерживать разделение index и work-tree, или объединить их в просто изменение дерева работы).

То, что делает специальный штамп, заключается в том, что он совершает это: два или, с -u или -a, даже три коммиты - выполняются в необычной форме (в качестве фиксации слияния, которая на самом деле не является слиянием) и не помещается на какую-либо ветвь (вместо этого используется специальная ссылка refs/stash, чтобы сохранить и найти их).

Поскольку они не находятся на ветке, rebase не касается их, а в вашем рабочем процессе это git stash pop, которое приносит изменения дерева работ в новое рабочее дерево. Однако, если вы сделаете свою собственную (нормальную) фиксацию, на ветке и переустановите и включите эту фиксацию, эта нормальная фиксация будет переустановлена ​​вместе с любыми другими. Через минуту мы займемся одной последней проблемой; на данный момент, давайте нарисуем это, так как серия коммитов, которые (или не делают), переустанавливаются:

... do some work ...
... make some commits ...
... more work ...
... do something that causes upstream/master to update, such as git fetch upstream
$ git stash

В этот момент, вот что у вас есть:

... - o - * - A - B - C     <-- HEAD=master
           \          |\
            \         i-w   <-- stash
             \
              @[email protected]@         <-- upstream/master

Здесь A, B и C - ваши коммиты (предположим, вы сделали 3), все на ветке master. i-w hanging off commit C - ваш трюк, который не находится на ветке, но по-прежнему представляет собой двухпартийный git пакетный портфель и фактически привязан к вашей последней фиксации (C). Записывается @ (может быть только один) - это новый восходящий поток.

(Если вы не совершили никаких коммитов, ваша сумка для зависания отменяет фиксацию *, и ваша текущая ветка указывает на фиксацию *, так что git rebase не имеет работы, кроме перемещения текущего указателя ветвления вперед. В этом случае все работает одинаково, но я предполагаю, что есть некоторые коммиты.)

Теперь вы запустите git rebase upstream/master. Это копирует ваши коммиты на новые коммиты, с новыми идентификаторами и новыми родительскими идентификаторами, чтобы они сидели поверх последнего @. Шкатулка не перемещается, поэтому результат выглядит следующим образом:

... - o - * - A - B - C     [abandoned, except for the stash]
           \          |\
            \         i-w   <-- stash
             \
              @[email protected]@         <-- upstream/master
                   \
                    A'-B'-C'   <-- HEAD=master

Теперь вы используете git stash pop, который восстанавливает элемент i/w в качестве изменений дерева работы, стирая метку stash (точнее, выталкивая ее так, чтобы [email protected]{1}, если она существует, теперь stash, и так далее). Это освобождает последние ссылки на исходную цепочку A - B - C и означает, что нам не нужен бит i-w, что позволяет нам перерисовать это как намного проще:

... - @            <-- upstream/master
       \
        A'-B'-C'   <-- HEAD=master plus work tree changes

Теперь давайте рисуем, что произойдет, если вместо git stash save вы просто сделаете git commit -a (или git add и git commit без -a), чтобы создать фактическое commit D. Вы начинаете с:

... - o-*-A-B-C-D   <-- HEAD=master
         \
          @[email protected]@     <-- upstream/master

Теперь вы git rebase upstream/master, который копирует A через D, чтобы поместить их в конец последнего @, и у вас есть это:

... - o-*[email protected]@[email protected]     <-- upstream/master
               \
                A'-B'-C'-D'   <-- HEAD=master

Единственная проблема заключается в том, что у вас есть этот лишний дополнительный commit D (ну, теперь D'), а не без изменений. Но это тривиально отменено с помощью git reset, чтобы отступить на один фиксатор. Мы можем использовать --mixed reset - по умолчанию - для того, чтобы изменить индекс (область постановки), чтобы "un-add" всех файлов или если вы хотите, чтобы они остались git add - ed, a --soft reset. (Не влияет на итоговый граф фиксации, только состояние индекса отличается.)

git reset --mixed HEAD^   # or leave out `--mixed` since it the default

Вот что это выглядит:

... - o-*[email protected]@[email protected]     <-- upstream/master
               \
                A'-B'-C'      <-- HEAD=master
                        \
                         D'   [abandoned]

Возможно, вы считаете, что это неэффективно, но когда вы используете git stash, вы на самом деле делаете не менее двух коммитов, которые затем вы покидаете позже, когда вы git stash pop их. Реальная разница заключается в том, что, совершая временные комманды не для публикации, вы автоматически их переустанавливаете.

Не бойтесь временных коммитов

Существует общее правило с git: сделать много временных коммитов, чтобы сохранить вашу работу по ходу дела. Вы всегда можете переустановить их позже. То есть вместо этого:

... - * - A - B - C   <-- mybranch

где A, B и C являются совершенными и окончательными совершаются на вершине commit * (от кого-то другого или ранее опубликованного материала), сделайте следующее:

... - * - a1 - a2 - b1 - a3 - b2 - a4 - b3 - c1 - b4 - c2 - c3

где a1 - начальный stab at A, a2 исправляет ошибку в a1, b1 - это первоначальная попытка заставить B работать, a3 - понять, что b1 требует, чтобы A был другим, b2 исправляет ошибку в b1, a4 исправляет ошибку в a3, меняет на a2, а b3 - это то, что должно было сделать b1; то c1 является начальной попыткой в ​​C, b4 является еще одним исправлением для b1, c2 является уточнением и т.д.

Скажем, что после c3 вы думаете, что он в основном готов. Теперь вы запустите git rebase -i origin/master или что-то еще, перетасуйте строки pick, чтобы получить a1 через a4 в порядок, b1 через b4 в порядок и c1 через c3 в порядок, и пусть перезапуск. Затем вы исправляете любые конфликты и убедитесь, что все еще правильно, затем вы запускаете еще один git rebase -i, чтобы свернуть все четыре версии A в A и т.д.

Когда все закончится, похоже, что вы создали идеальный A в первый раз (или, может быть, с a4 или какой-либо другой, в зависимости от того, что вы обязуетесь и какие из них вы отбрасываете, устанавливать любые отметки времени в вещах). Другие люди могут не хотеть или не видеть вашу промежуточную работу, хотя вы можете сохранить ее, а не комбинировать коммиты, если это полезно. Между тем вам никогда не нужно иметь непредусмотренные вещи, которые вам нужно переустанавливать, потому что вы просто совершаете частичные вещи.

Это помогает дать эти имена коммитов в текстовом тексте с одной строкой, который будет вести вашу последующую работу по перестановке:

git commit -m 'temp commit: work to enable frabulator, incomplete'

и т.д.

Ответ 2

Один простой ответ: git rebase -i --autosquash --autostash <tree-ish>

-i = interactively rebase

https://devdocs.io/git/git-rebase


Это будет...

  • Автоматическое сохранение ваших изменений.
  • Интерактивно rebase от <tree-ish>
    • Автоматическое размещение ваших сквош и исправлений
  • Автоматический pop stash в рабочем каталоге после rebase

tree-ish может быть хешем фиксации или именем ветки или тегом или любой идентификатор.

Ответ 3

Вы можете использовать внешние инструменты под названием git-up, что делает именно то, что вы говорите для всех ветвей. Это также поможет вам сохранить чистый график истории.

Я использовал несколько лет, и он работает очень хорошо, особенно если вы не эксперт git. Если вы добавите функцию автовосстановления, вы должны знать, как правильно восстанавливаться после отказа от переустановки (продолжить, прервать,...)

Установка

Откройте оболочку и запустите:

sudo gem install git-up

Конфигурация

Откройте глобальный файл конфигурации (~/.gitconfig) и добавьте следующее:

[git-up "fetch"]
    all = true    # up all branches at once, default false
    prune = true  # prune deleted remote branches, default false
[git-up "rebase"]
    # recreate merges while rebasing, default: unset
    arguments = --preserve-merges
    # uncomment the following to show changed commit on rebase
    # log-hook = "git --no-pager log --oneline --color --decorate $1..$2"

Подробнее... официальная документация.

Призвание

Если все настроено хорошо, просто запустите:

git up

Это (примерно) эквивалент выполнения следующих действий:

git stash
git fetch --all
[foreach branch]
    git rebase --preserve-merges <branch> <remote>/<branch>
    git merge --ff-only <branch>
[end foreach]
git checkout <prev_branch>
git stash pop

Ответ 4

Весь рабочий процесс в одной команде, включая выборку:

git pull --rebase --autostash [...]

Ответ 5

Ответа на этот вопрос tjsingleton blogg

введите псевдоним команды:

git stash && & git pull --rebase && & git stash pop

Обновление

Если вы используете идею, нажав на грязную рабочую директорию, она предложит диалог, выберете rebase/merge, он будет делать stash, rebase/merge и pop автоматически.