push --force-with-lease domyślnie

133

Właśnie się dowiedziałem git push --force-with-lease. To niesamowite. Ale oczywiście nie używam siły tak często, więc martwię się, że mogę zapomnieć o tej fajnej funkcji, gdy będę jej potrzebować następnym razem.

Czy istnieje sposób na skonfigurowanie gita, aby git push -fużywał go automatycznie, --force-with-leasechyba że celowo go zastąpię --no-force-with-lease?

(Nie wyobrażam sobie, żebym kiedykolwiek chciał użyć siły bez dzierżawy!)

Dan Fabulich
źródło

Odpowiedzi:

143

AFAIK, nie ma dostępnej konfiguracji, która powiedziałaby gitowi, aby zawsze używał force-with-leasezamiast force. Wydaje się, że to dobry przykład na żądanie funkcji; jeśli nie masz problemu z zanurzeniem się w bazie kodu git, możesz zaimplementować go samodzielnie i przesłać do przeglądu.

EDYCJA W obecnej postaci jest to nadal aktualne w kwietniu 2019 r.

Do tego czasu jedyną opcją, jaką widzę, jest, jak to często bywa, utworzenie, aliasktóre służy do tego celu.

Utwórz alias

Aby utworzyć alias git config --global alias.<alias-name> <command>, w naszym przypadku sugerowałbym coś podobnego.

git config --global alias.pushf "push --force-with-lease"

Spowoduje to utworzenie wpisu w .gitconfigpliku globalnym (który zwykle można znaleźć w swoim katalogu domowym ). Następnie możesz po prostu użyć git pushfdo wymuszenia z dzierżawą .

Zabrudz sobie ręce

Jeśli chcesz zaimplementować tę funkcję samodzielnie, ale nie jesteś pewien, od czego zacząć, powinieneś najpierw spojrzeć na katalog dokumentacji w repozytorium git . Tutaj możesz znaleźć wskazówki dotyczące kodowania i informacje o tym, jak przesyłać poprawki .

Możesz znaleźć wszystkie te linki i więcej na oficjalnej stronie społeczności .

Sascha Wolf
źródło
25
Uwaga na temat tego, że nie jest to funkcja: częstym argumentem przeciwko przepisywaniu standardowych poleceń („push --force”) jest to, że przyzwyczajasz się do nich, zapominasz o ich pochodzeniu i pewnego dnia przypadkowo używasz ich w ten sposób w nowym systemie. Podobnie jak aliasing rmdo rm -iw twoim .bashrc; pewnego dnia zapomnisz i usuniesz ważny plik na serwerze. Idąc z własnym aliasem nie ma tego problemu :)
hraban
3
Osobista anegdota / uwaga: próbowałem pushfużyć push -faliasu, ale zawsze dwukrotnie sprawdzałem, czy nie robię , ponieważ wygląda podobnie do aliasu. Niektórzy członkowie zespołu i push -ftak go używali , myśląc, że alias jest dla niego tylko kosmetycznym skrótem. Ostatecznie zmieniliśmy bezpieczniejszą formę na alias pushfli przestaliśmy się tym martwić.
kelvin
31

Martwię się, że mogę zapomnieć o tej fajnej funkcji, gdy będę jej potrzebować następnym razem.

Git 2.13 (Q2 2017) wyjaśnia, dlaczego nie ma „ochrony” przed zapomnieniem tej opcji wypychania, ponieważ nawet jeśli nie zapomnisz jej na git pushpoziomie, może ona zostać zignorowana.

Zobacz commit f17d642 (19 kwietnia 2017) autorstwa Ævara Arnfjörð Bjarmason ( avar) .
(Scalone przez Junio ​​C Hamano - gitster- w zobowiązaniu 46bdfa3 , 26 kwietnia 2017 r.)

push: dokumentuj i testuj za --force-with-leasepomocą wielu pilotów

Dokumentuj i testuj w przypadkach, w których istnieją dwa piloty wskazujące ten sam adres URL, a pobieranie w tle i kolejne git push --force-with-leasenie powinny blokować niezaktualizowanych referencji, których nie pobraliśmy.

Niektóre edytory, takie jak Microsoft VSC, mają funkcję automatycznego pobierania w tle, co omija zabezpieczenia oferowane przez --force-with-lease&--force-with-lease=<refname> , jak wspomniano w dodawanej tutaj dokumentacji.

Tak więc dokumentacja nagit push razie obejmuje:

ogólna uwaga na temat bezpieczeństwa: dostarczanie tej opcji bez oczekiwanej wartości, tj. jako --force-with-leaselub --force-with-lease=<refname> bardzo źle współdziała z wszystkim, co niejawnie działa git fetchna pilocie, do którego ma być przesłany w tle, np. git fetch origin w repozytorium w pracy cron.

Ochrona, którą oferuje, --forcepolega na zapewnieniu, że kolejne zmiany, na których nie opierała się twoja praca, nie są blokowane, ale jest to trywialne pokonanie, jeśli jakiś proces w tle aktualizuje referencje w tle. Nie mamy nic oprócz informacji o zdalnym śledzeniu, które można wykorzystać jako heurystykę dla referencji, których oczekujesz, że widziałeś i chcesz się przebić.

Jeśli twój edytor lub inny system działa git fetchw tle, sposobem na złagodzenie tego jest po prostu skonfigurowanie innego pilota:

git remote add origin-push $(git config remote.origin.url)
git fetch origin-push

Teraz, gdy proces w tle zostanie uruchomiony, git fetch originodniesienia origin-pushnie zostaną zaktualizowane, a zatem polecenia takie jak:

git push --force-with-lease origin-push

Nie powiedzie się, chyba że uruchomisz ręcznie git fetch origin-push.
Ta metoda jest oczywiście całkowicie pokonana przez coś, co działa git fetch --all, w takim przypadku musisz ją wyłączyć lub zrobić coś bardziej żmudnego, na przykład:

git fetch              # update 'master' from remote
git tag base master    # mark our base point
git rebase -i master   # rewrite some commits
git push --force-with-lease=master:base master:master

Czyli utworzyć basetag dla wersji kodu upstream, które widziałem i są gotowi zastąpić, a następnie przepisać historię, i wreszcie zmusić do zmiany wypychania masterjeśli pilot jest nadal w wersji base, niezależnie od tego, co się z lokalnym remotes/origin/masterzostała zaktualizowana w tło.

VonC
źródło
30

Moim rozwiązaniem było stworzenie skryptu opakowującego i użycie aliasu, aby zawsze używać go zamiast prawdziwego git.

Ilekroć próbuję git push -f, widzę następujące informacje:

⚡ git push -f
use this instead so you don't cause race conditions in the 
repo: git push --force-with-lease

Niektóre zalety tego skryptu to:

  • uczy mnie zwykłego używania --force-with-lease, więc nie denerwuję się, gdy się mylę
  • jeśli z jakiegoś powodu naprawdę musimy forsować, git push --forcezadziała.

Jak to wdrożyć:

  1. utwórz niestandardowy skrypt, który przejdzie przez wszystkie parametry do git, z wyjątkiem -f
  2. alias ten skrypt, więc używamy go zamiast git

Te instrukcje zakładają Linuksa lub Maca z uruchomionym bash. Nie próbowałem tego z zsh lub Windows, ale zakładam, że to też zadziała.

~/.bash_profile:

alias git=~/.git_wrapper.sh

~./git_wrapper.sh:

#!/bin/bash
for arg in "$@"; do
    if [ "$arg" = "push" ]; then
        ispush=1
    elif [ "$ispush" = 1 -a "$arg" = '-f' ]; then
        echo "use this instead so you don't cause race conflicts in the repo: git push --force-with-lease"
        exit 1
    fi
done

git "$@"

Po tych zmianach zrestartuj terminal i gitpowinieneś teraz być zarozumiały, gdy spróbujesz wymusić push.

Jessica Knight
źródło
18
To wydaje się wygodne. +1. Może zamienić „hej idioto” na „hej, ty delikatna, ale prosta duszo” lub coś w tym rodzaju;)
VonC
5

Dla osób używających OMYZSH możesz po prostu użyć ggfl.

Nicolas
źródło
3

Chcę, aby przypomniało mi się, że nie powinienem używać -f, ale nie chcę dać się zwieść i uwierzyć, że -fto oznacza --force-with-lease. Więc to jest moje podejście:

git() {
  if [[ $@ == 'push -f'* ]]; then
    echo Hey stupid, use --force-with-lease instead
  else
    command git "$@"
  fi
}

Dodaj do swojej .bash_profile, .bashrclub .zshrc.

neu242
źródło
1

Możesz utworzyć funkcję bash, która zastępuje giti używa --force-with-leasezamiast--force

# replaces `git push --force` with `git push --force-with-lease`
git() {
  if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then
    command git push --force-with-lease
  else
    command git "$@"
  fi
}

lub w jednym wierszu:

git() { if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then command git push --force-with-lease; else command git "$@"; fi; }

Po prostu dodaj go do swojego ~/.bashrclub ~/.zshrc.

paulodiovani
źródło