Если целью является вызов функции some_func
с классом в качестве аргумента, один ответ заключается в объявлении some_func
в качестве декоратора класса. Обратите внимание, что декоратор класса вызывается после инициализации класса. Он будет передан классу, который оформляется в качестве аргумента.
def some_func(cls):
# Do something
print(f"The answer is {cls.x}")
return cls # Don't forget to return the class
@some_func
class A:
x = 1
Если вы хотите передать дополнительные аргументы в some_func
, вы должны вернуть функцию из декоратора:
def some_other_func(prefix, suffix):
def inner(cls):
print(f"{prefix} {cls.__name__} {suffix}")
return cls
return inner
@some_other_func("Hello", " and goodbye!")
class B:
x = 2
Декораторы классов могут быть скомпонованы, что приводит к их вызыванию в обратном порядке, которые они объявляются:
@some_func
@some_other_func("Hello", "and goodbye!")
class C:
x = 42
. Результатом является:
# Hello C and goodbye!
# The answer is 42
Вы можете использовать git rebase, например, если вы хотите изменить обратно для фиксации bbc643cd
, запустите
$ git rebase --interactive 'bbc643cd^'
В редакторе по умолчанию измените от pick
до edit
в строке чей коммит вы хотите изменить. Внесите свои изменения, а затем передайте их с тем же сообщением, которое вы имели до:
$ git commit --all --amend --no-edit
, чтобы изменить фиксацию, и после этого
$ git rebase --continue
, чтобы вернуться к предыдущей фиксации головы.
ПРЕДУПРЕЖДЕНИЕ : обратите внимание, что это изменит SHA-1 этого коммита , а также всех потомков - другими словами, это переписывает историю с этого момента. Вы можете разбить репо, выполнив это , если нажмете команду git push --force
Если вы еще не выдвинули коммиты, вы можете вернуться к предыдущему коммиту, используя git reset HEAD^[1,2,3,4...]
Например
git commit <file1> -m "Updated files 1 and 2"
git commit <file3> -m "Updated file 3"
Упс, забыли добавить файл2 в первый коммит ...
git reset HEAD^1 // because I only need to go back 1 commit
git add <file2>
Это добавит файл2 к первому коммиту.
git stash
+ rebase
автоматизация
Поскольку, когда мне нужно много раз модифицировать старый коммит для обзоров Геррита, я делаю:
git-amend-old() (
# Stash, apply to past commit, and rebase the current branch on to of the result.
current_branch="$(git rev-parse --abbrev-ref HEAD)"
apply_to="$1"
git stash
git checkout "$apply_to"
git stash apply
git add -u
git commit --amend --no-edit
new_sha="$(git log --format="%H" -n 1)"
git checkout "$current_branch"
git rebase --onto "$new_sha" "$apply_to"
)
Использование:
git-amend-old $old_sha
Мне нравится это над --autosquash
, так как оно не раздавливает другие несвязанные исправления.
Чтобы получить неинтерактивную команду, поместите сценарий с этим содержимым в переменную PATH:
#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"
Используйте его, подготовив изменения (с помощью git add
), и затем запустите git fixup <commit-to-modify>
. Конечно, он все равно будет интерактивным, если вы столкнетесь с конфликтами.
На основе Документации
Исправление сообщения более старых или сообщений о множественной фиксации
git rebase -i HEAD~3
Выше показан список последних 3 фиксирует в текущей ветви, измените 3 на что-то другое, если хотите больше Список будет выглядеть примерно так:
pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.
Замените , выберите на , переформулируйте перед каждым сообщением о коммите, которое вы хотите изменить. Допустим, вы изменили второй коммит в списке, ваш файл будет выглядеть следующим образом:
pick e499d89 Delete CNAME
reword 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.
Сохраните и закройте файл списка коммитов, появится новый редактор для вас, чтобы изменить ваше сообщение коммита , измени сообщение коммита и сохрани.
Finaly Force-push исправленных коммитов.
git push --force
Если по какой-то причине вам не нравятся интерактивные редакторы, вы можете использовать git rebase --onto
.
Скажем, вы хотите изменить Commit1
. Во-первых, ответвьте от до Commit1
:
git checkout -b amending [commit before Commit1]
Во-вторых, возьмите Commit1
с cherry-pick
:
git cherry-pick Commit1
Теперь внесите изменения, Создание Commit1'
:
git add ...
git commit --amend -m "new message for Commit1"
И, наконец, после того, как спрятали любые другие изменения, перенесите оставшиеся коммиты до master
поверх вашего нового коммита:
git rebase --onto amending Commit1 master
Читать: «перебазировать на ветку amending
все коммиты между Commit1
(не включительно) и master
(включительно)». То есть, Commit2 и Commit3, полностью исключая старый Commit1. Вы можете просто выбрать их, но так проще.
Не забудьте почистить свои ветви!
git branch -d amending
Пришел к такому подходу (и он, вероятно, точно такой же, как использование интерактивной перебазировки), но для меня это довольно просто.
Примечание: я представляю этот подход для иллюстрации того, что вы можете сделать, а не для повседневной альтернативы. Так как в нем много шагов (и, возможно, несколько предостережений).
Скажем, вы хотите изменить коммит 0
, и вы в настоящее время находитесь на feature-branch
some-commit---0---1---2---(feature-branch)HEAD
. а quick-branch
. Вы также можете клонировать свою функциональную ветвь как точку восстановления (перед запуском).
?(git checkout -b feature-branch-backup)
git checkout 0
git checkout -b quick-branch
Теперь у вас будет что-то вроде этого:
0(quick-branch)HEAD---1---2---(feature-branch)
Смена сцены, спрятать все остальное.
git add ./example.txt
git stash
Передать изменения и оформить заказ обратно на feature-branch
git commit --amend
git checkout feature-branch
Теперь у вас будет что-то вроде этого:
some-commit---0---1---2---(feature-branch)HEAD
\
---0'(quick-branch)
Перебазировать feature-branch
на quick-branch
( разрешать любые конфликты по пути). Примените тайник и удалите quick-branch
.
git rebase quick-branch
git stash pop
git branch -D quick-branch
И вы получите:
some-commit---0'---1'---2'---HEAD(feature-branch)
Git не будет дублировать (хотя я не могу точно сказать, в какой степени) коммит 0 при ребазинге.
Примечание: все хеши коммитов меняются, начиная с коммита, который мы изначально намеревались изменить.
Интерактивный ребаз с --autosquash
- это то, что я часто использую, когда мне нужно исправить предыдущие коммиты глубже в истории. Это существенно ускоряет процесс, который иллюстрирует ответ ZelluX, и особенно удобно, когда вам нужно отредактировать более одного коммита.
Из документации:
--autosquash
Когда сообщение журнала фиксации начинается с «squash!…» (Или «fixup!…»), И там это коммит, название которого начинается с того же самого…, автоматически изменяйте список задач rebase -i, чтобы коммит, помеченный для сквошинга, пришел сразу после коммита, подлежащего изменению
Предположим, у вас есть история это выглядит следующим образом:
$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1
и у вас есть изменения, которые вы хотите изменить в Commit2, затем зафиксируйте свои изменения, используя
$ git commit -m "fixup! Commit2"
, в качестве альтернативы вы можете использовать commit-sha вместо сообщение коммита, так что "fixup! e8adec4
или даже просто префикс сообщения коммита.
Затем инициируйте интерактивную перебазировку при коммите до
$ git rebase e8adec4^ -i --autosquash
, ваш редактор откроется с коммитами, уже правильно упорядоченными
pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3
, все что вам нужно сделать, это сохранить и выйти
Наилучший вариант состоит в том, чтобы использовать "Интерактивная переосновная команда" .
Эти
git rebase
команда невероятно мощна. Это позволяет Вам редактировать сообщения о фиксации , комбинировать фиксации, переупорядочивать их... и т.д.Каждый раз, когда Вы повторно основываете фиксацию, новый SHA будет создан для каждой фиксации независимо от содержания, будет изменен или нет! Необходимо быть осторожными, когда использовать эту причину команды, она может иметь решительные последствия особенно, если Вы работаете в сотрудничестве с другими разработчиками. Они могут начать работать с Вашей фиксацией, в то время как Вы повторно основываете некоторых. После принуждения для продвижения фиксаций, которыми они будут вне синхронизации, и можно узнать позже в грязной ситуации. Так будьте осторожны!
рекомендуется создать
backup
ответвление прежде, чем повторно базироваться поэтому каждый раз, когда Вы находите вещи из-под контроля, можно возвратиться назад к предыдущему состоянию.
git rebase -i <base>
-i
обозначают [1 160] "интерактивный" . Обратите внимание, что можно выполнить переоснову в неинтерактивном режиме. исключая:
#interactivly rebase the n commits from the current position, n is a given number(2,3 ...etc)
git rebase -i HEAD~n
HEAD
указывает на Ваше текущее местоположение (может быть также имя ответвления или фиксировать SHA). Эти ~n
означает "n beforeГ©, таким образом HEAD~n
будет список фиксаций "n" перед той, Вы в настоящее время включены.
git rebase
имеет другую команду как:
p
или pick
для хранения фиксации как есть r
или reword
: сохранить содержание фиксации, но изменить сообщение о фиксации. s
или squash
: объединить изменения этой фиксации в предыдущую фиксацию (фиксация выше его в списке). ... и т.д.
Примечание: лучше заставить Мерзавца, работающего с Вашим редактором кода делать вещи более простыми. Как, например, если Вы используете визуальный код, можно добавить как это git config --global core.editor "code --wait"
. Или можно искать в Google, как связать Вас, предпочел Ваш редактор кода с МЕРЗАВЦЕМ.
я хотел изменить последние 2 фиксации, которые я сделал так, я обрабатываю как это:
#This to show all the commits on one line
$git log --oneline
4f3d0c8 (HEAD -> documentation) docs: Add project description and included files"
4d95e08 docs: Add created date and project title"
eaf7978 (origin/master , origin/HEAD, master) Inital commit
46a5819 Create README.md
Теперь я использую git rebase
для изменения 2 последних сообщений фиксаций: $git rebase -i HEAD~2
Это открывает редактор кода, и покажите это:
pick 4d95e08 docs: Add created date and project title
pick 4f3d0c8 docs: Add project description and included files
# Rebase eaf7978..4f3d0c8 onto eaf7978 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
...
, Так как я хочу изменить сообщение о фиксации для этого 2 фиксации. Таким образом, я введу r
или reword
вместо [1 126]. Затем Сохраните файл и закройте вкладку. Обратите внимание, что rebase
выполняется в многоступенчатом процессе, таким образом, следующий шаг должен обновить сообщения. Обратите внимание также, что фиксации отображены в обратном хронологическом порядке, таким образом, последняя фиксация отображена в той и первой фиксации в первой строке и т.д.
Обновление сообщения: Обновите первое сообщение:
docs: Add created date and project title to the documentation "README.md"
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
...
сохраняют и закрывают Редактирование, которое второе сообщение
docs: Add project description and included files to the documentation "README.md"
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
...
сохраняет и закрывает.
Вы получите сообщение как это к концу переосновы: Successfully rebased and updated refs/heads/documentation
, что означает, что Вы успешно выполняетесь. Можно отобразить изменения:
5dff827 (HEAD -> documentation) docs: Add project description and included files to the documentation "README.md"
4585c68 docs: Add created date and project title to the documentation "README.md"
eaf7978 (origin/master, origin/HEAD, master) Inital commit
46a5819 Create README.md
я желаю, чтобы это могло помочь новым пользователям :).