Необходимость 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.

Обязательное слово предупреждения: если вы работаете в публичном репозитории, на котором работают другие люди, и вам нужен этот псевдоним, вы это делаете неправильно ™.