Необходимость reset git от ветвления к исходной версии
Я случайно работал над веткой, я не должен был быть на некоторое время, поэтому я отделил ее, указав соответствующее имя. Теперь я хочу перезаписать ветку, на которой я не должен был перейти к исходной версии (github). Есть простой способ сделать это? Я попытался удалить ветку, а затем сбросить ветвь отслеживания, но она просто дает мне версию, над которой я работал снова.
Ответы
Ответ 1
Если вы еще не нажали на источник, вы можете сбросить свою ветку на восходящую ветку с помощью:
git checkout mybranch
git reset --hard origin/mybranch
(убедитесь, что вы ссылаетесь на свой последний коммит в отдельной ветке, как вы упоминали в своем вопросе)
Обратите внимание, что сразу после сброса [email protected]{1}
ссылается на старый коммит, до сброса.
Но если вы уже нажали, см. "Создать ветку git и вернуть исходный в исходное состояние" для других вариантов.
С Git 2.23 (август 2019 г.) это будет одна команда: git switch
.
А именно: git switch -C mybranch origin/mybranch
Пример
C:\Users\vonc\git\git>git switch -C master origin/master
Reset branch 'master'
Branch 'master' set up to track remote branch 'master' from 'origin'.
Your branch is up to date with 'origin/master'.
Это восстанавливает индекс и рабочее дерево, как git reset --hard
.
Как прокомментировал Брэд Херман, reset --hard
удалит любой новый файл или сбросит измененный файл в HEAD.
На самом деле, чтобы убедиться, что вы начинаете с "чистого листа", git clean -f -d
после сброса обеспечит рабочее дерево, точно идентичное ветки, в которую вы только что сбросили.
В этом блоге предлагаются эти псевдонимы (только для ветки master
, но вы можете их адаптировать/расширять):
[alias]
resetorigin = !git fetch origin && git reset --hard origin/master && git clean -f -d
resetupstream = !git fetch upstream && git reset --hard upstream/master && git clean -f -d
Затем вы можете ввести:
git resetupstream
или
git resetorigin
Ответ 2
Предполагая, что это произошло:
# on branch master
vi buggy.py # you edit file
git add buggy.py # stage file
git commit -m "Fix the bug" # commit
vi tests.py # edit another file but do not commit yet
Затем вы понимаете, что делаете изменения на неправильной ветке.
git checkout -b mybranch # you create the correct branch and switch to it
Но master
все еще указывает на вашу фиксацию. Вы хотите, чтобы он указывал, где он указывал раньше.
Решение
Самый простой способ:
git branch --force master origin/master
Другой способ:
git checkout master
git reset --soft origin/master
git checkout mybranch
Обратите внимание, что использование reset --hard
приведет к потере ваших незафиксированных изменений (tests.py
в моем примере).
Ответ 3
У меня есть частное репо на сервере и регулярно переустанавливаю/принудительно нажимаю на него, что часто необходимо для reset локальной ветки на моем другом компьютере. Поэтому я создал следующий псевдоним "catchup", который позволяет делать это для текущей ветки. В отличие от другого ответа в этом псевдониме нет жестко заданного имени ветки.
Держитесь крепко.
[alias]
catchup = "!f(){ echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \"; read -r ans; if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)); else echo \"catchup aborted\"; fi }; f"
Правильно отформатированный (не будет работать с новыми строками в .gitconfig) выглядит следующим образом:
"
!f(){
echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \";
read -r ans;
if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then
git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD));
else
echo \"catchup aborted\";
fi
}; f
"
-
\\033[0;33m
и \\033[0m
предназначены для выделения текущей ветки и восходящего потока с цветом.
-
$(git symbolic-ref -q --short HEAD)
- текущее имя ветки
-
$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))
- это верхняя часть текущей ветки.
Так как reset - потенциально опасный вызов (особенно с параметром --hard, вы потеряете любые незафиксированные изменения), сначала он подскажет, что он собирается делать. Например, если вы используете ветвь dev-container с удаленным именем qcpp/dev-container и вы введете git catchup
, вам будет предложено:
reset dev-container для qcpp/dev-container? (Y/N)
Если вы затем наберете y или просто нажмите return, он выполнит reset. Если вы введете что-нибудь еще, reset не будет выполняться.
Если вы хотите быть супербезопасным и программным образом предотвращать потерю неустановленных/незавершенных изменений, вы можете сузить вышеуказанный псевдоним с помощью соответствующих проверок для diff-index.
Обязательное слово предупреждения: если вы работаете в публичном репозитории, на котором работают другие люди, и вам нужен этот псевдоним, вы это делаете неправильно ™.