Korzystanie z programu Git (index)


Korzystanie z programu Git (6) - konflikty

WPROWADZENIE

Podczas pracy z Gitem może pojawić się sytuacja, kiedy jeden plik w różnych wersjach jest poddany różnym modyfikacjom. Wtedy operacja łączenia wersji prowadzi do konfliktu. Konflikty można edytować ręcznie w plikach lub użyć wybranego narzędzia do obsługi konfliktu. Polecane narzędzia open source:

Pliki z konfliktami są specjalnie zaznaczane w indeksie, dlatego "git commit" nie uda się zrobić, a "git status" raportuje "unmerged files".

KONFLIKTY LOKALNE

Zakładam, że istnieją dwie gałęzie: master i testing.


$ git checkout master

$ git merge testing
# Pojawia się konflikt w pliku a1.txt.
# Przykładowy komunikat:
Auto-merging a1.txt
CONFLICT (content): Merge conflict in a1.txt
Automatic merge failed; fix conflicts and then commit the result.

$ git status
# On branch master
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#    both modified:      a1.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

$ cat a1.txt        # oglądamy miejsce konfliktu
plik a1
<<<<<<< HEAD
zmiana a1 w galezi master
=======
zmiana a1 w galezi testing
>>>>>>> testing

# Wywołanie konkretnego narzędzia do łączenia.
# git mergetool -t meld
# git mergetool --tool=meld

$ git mergetool
merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge
    gvimdiff diffuse ecmerge p4merge araxis bc3 emerge vimdiff
Merging:
a1.txt

Normal merge conflict for 'a1.txt':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (gvimdiff):

# Po zainstalowaniu KDiff3 i Meld domyślnie uruchamia się Meld.
# Po wykonaniu edycji a1.txt jest zmieniony, a poprzednia wersja
# jest zapisana w pliku a1.txt.orig.
# Czasem jest pytanie od Gita, czy konflikt jest rozwiązany
# (Git nie pyta, kiedy skorzystał z exit code).

$ git status        # sprawdzamy stan repo
# On branch master
# Changes to be committed:
#
#    modified:   a1.txt
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    a1.txt.orig

$ rm a1.txt.orig    # usuwam wersję z zaznaczonymi konfliktami

$ git add -A

$ git commit -m "Merge branch testing."

SYNCHRONIZACJA REPOZYTORIÓW

Zakładam, że lokalna gałąź master śledzi gałąź origin/master.


# Repo zdalne to mgr-tmp.
# W repo1 i repo2 jest plik a1, jest synchronizacja.
# W repo2 tworzę plik b1 i robię git push.
# W repo1 tworzę plik a2 i git push się nie udaje (non-fast-forward):

$ git push
Password for 'https://ufkapano@bitbucket.org': 
To https://ufkapano@bitbucket.org/ufkapano/mgr-tmp.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'https://ufkapano@bitbucket.org/ufkapano/mgr-tmp.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

# W repo1 robię git pull, udaje się, historia jest nieliniowa.
# Nowa rewizja to "Merge branch 'master' of mgr-tmp".
# W repo1 robię git push.
# W repo2 robię git pull, jest synchronizacja.

# W repo2 zmieniam a2 i robię git commit, git push.
# W repo1 zmieniam a2, robię git commit. git push się nie udaje.
# W repo1 robię git fetch.
# Uaktualnia się origin/master. Próbuje git rebase.

$ git rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: a2 changed on dell.
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging tests/a2.txt
CONFLICT (content): Merge conflict in tests/a2.txt
Failed to merge in the changes.
Patch failed at 0001 a2 changed on dell.

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".

# Zmiana z repo2 jest nałożona.
# W pliku a2 jest zaznaczony konflikt.
# Zmieniam ręcznie rewizję zrobioną w repo1.
# Ta stara rewizja z repo1 nie będzie widziana w historii!

$ git add -A

$ git rebase --continue

$ git push

# W repo2 zmieniam a2 i robię git commit, git push.
# W repo1 zmieniam a2, robię git commit. git push się nie udaje.
# W repo1 robię git fetch.
# Uaktualnia się origin/master. Próbuje git merge.

$ git merge origin/master
Auto-merging tests/a2.txt
CONFLICT (content): Merge conflict in tests/a2.txt
Automatic merge failed; fix conflicts and then commit the result.

# Konflikt rozwiązuje ręcznie.

$ git add -A

$ git commit -m "Merge branch origin/master."

$ git push

ZADANIE 6.1


Korzystanie z programu Git (index)