У овом чланку ћете научити о различитим начинима да се играте са урезима у Гиту.
Као програмер, наишли бисте на такве ситуације више пута у којима бисте желели да се вратите на једно од својих претходних урезивања, али нисте сигурни како то да урадите. Чак и ако знате Гит команде као што су ресетовање, враћање, ребасе, нисте свесни разлика између њих. Дакле, хајде да почнемо и разумемо шта су гит ресетовање, враћање и ребазовање.
Преглед садржаја
Гит Ресет
Гит ресет је сложена команда и користи се за поништавање промена.
Можете замислити гит ресет као функцију враћања. Са гит ресетовањем, можете скакати између различитих урезивања. Постоје три начина покретања гит ресет команде: –софт, –микед и –хард. Подразумевано, гит ресет команда користи мешовити режим. У току рада за ресетовање гит-а, три интерна механизма управљања гит-ом долазе у слику: ГЛАВА, област за постављање (индекс) и радни директоријум.
Радни директоријум је место где тренутно радите, то је место где су ваше датотеке присутне. Користећи гит статус команду, можете видети који су све фајлови/фолдери присутни у радном директоријуму.
Стагинг Ареа (Индек) је место где гит прати и чува све промене у датотекама. Сачуване промене се одражавају у .гит директоријуму. Користите гит адд „име датотеке“ да додате датотеку у област за припрему. И као и раније, када покренете гит статус, видећете које датотеке су присутне у области за припрему.
Тренутна грана у Гиту се назива ХЕАД. Указује на последњу урезивање, која се десила у тренутној грани за одјаву. Третира се као показивач за било коју референцу. Када одете у другу грану, ГЛАВА се такође помера у нову грану.
Дозволите ми да објасним како гит ресет функционише у тврдом, меком и мешовитом режиму. Тврди режим се користи за прелазак на урезано урезивање, радни директоријум се попуњава датотекама тог урезивања, а област за постављање се ресетује. У меком ресетовању, само се показивач мења на наведено урезивање. Датотеке свих урезивања остају у радном директоријуму и области за постављање пре ресетовања. У мешовитом режиму (подразумевано), показивач и област за постављање се ресетују.
Гит Ресет Хард
Сврха гит хард ресетовања је да се ХЕАД помери на наведено урезивање. Уклониће сва урезивања која су се десила након наведеног урезивања. Ова команда ће променити историју урезивања и указивати на наведено урезивање.
У овом примеру ћу додати три нове датотеке, урезати их и затим извршити хард ресет.
Као што можете видети из наредбе испод, тренутно нема шта да се урезује.
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean
Сада ћу направити 3 датотеке и додати им нешто садржаја.
$ vi file1.txt $ vi file2.txt $ vi file3.txt
Додајте ове датотеке у постојеће спремиште.
$ git add file*
Када поново покренете команду статуса, она ће одражавати нове датотеке које сам управо направио.
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: file1.txt new file: file2.txt new file: file3.txt
Пре урезивања, дозволите ми да вам покажем, тренутно имам дневник од 3 урезивања у Гиту.
$ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Сада ћу се посветити спремишту.
$ git commit -m 'added 3 files' [master d69950b] added 3 files 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txt
Ако урадим лс-фајлове, видећете да су нове датотеке додате.
$ git ls-files demo dummyfile newfile file1.txt file2.txt file3.txt
Када покренем наредбу дневника у гит-у, имам 4 урезивања, а ХЕАД указује на најновије урезивање.
$ git log --oneline d69950b (HEAD -> master) added 3 files 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Ако одем и избришем фајл1.ткт ручно и извршим гит статус, приказаће се порука да промене нису постављене за урезивање.
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) deleted: file1.txt no changes added to commit (use "git add" and/or "git commit -a")
Сада ћу покренути команду за хард ресет.
$ git reset --hard HEAD is now at d69950b added 3 files
Ако поново проверим статус, открићу да нема шта да се урезује, а датотека коју сам обрисао се вратила у спремиште. Враћање се догодило јер након брисања датотеке нисам урезао, па се након хард ресетовања вратио у претходно стање.
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean
Ако проверим дневник гит-а, овако ће изгледати.
$ git log commit d69950b7ea406a97499e07f9b28082db9db0b387 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 19:53:31 2020 +0530 added 3 files commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test
Сврха хард ресетовања је да укаже на наведено урезивање и ажурира радни директоријум и област за постављање. Дозволите ми да вам покажем још један пример. Тренутно, визуелизација мојих урезивања изгледа овако:
Овде ћу покренути команду са ХЕАД^, што значи да желим да се вратим на претходно урезивање (једно урезивање назад).
$ git reset --hard HEAD^ HEAD is now at 0db602e one more commit
Можете видети да је показивач главе сада промењен у 0дб602е са д69950б.
$ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Ако проверите дневник, урезивање д69950б је нестало, а глава сада показује на 0дб602е СХА.
$ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 Test
Ако покренете лс-датотеке, можете видети да филе1.ткт, филе2.ткт и филес3.ткт више нису у спремишту јер су то урезивање и његова датотека уклоњени након хард ресетовања.
$ git ls-files demo dummyfile newfile
Гит Софт Ресет
Слично томе, сада ћу вам показати пример меког ресетовања. Узмите у обзир, поново сам додао 3 фајла као што је горе поменуто и урезао их. Гит дневник ће се појавити као што је приказано испод. Можете видети да је ‘софт ресет’ моје најновије урезивање, а ХЕАД такође указује на то.
$ git log --oneline aa40085 (HEAD -> master) soft reset 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Детаљи урезивања у дневнику могу се видети помоћу доње команде.
$ git log commit aa400858aab3927e79116941c715749780a59fc9 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 21:01:36 2020 +0530 soft reset commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test
Сада користећи меко ресетовање, желим да пређем на једно од старијих урезивања са СХА 0дб602е085а4д59цфа9393абац41фф5фд7афцб14
Да бих то урадио, покренућу наредбу испод. Морате да проследите више од 6 почетних знакова СХА, комплетан СХА није потребан.
$ git reset --soft 0db602e085a4
Сада када покренем гит дневник, видим да је ХЕАД ресетован на урезивање које сам навео.
$ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test
Али разлика је у томе што су датотеке урезивања (аа400858ааб3927е79116941ц715749780а59фц9) где сам додао 3 датотеке још увек у мом радном директоријуму. Нису избрисани. Зато би требало да користите меко ресетовање уместо хард ресетовање. Не постоји ризик од губитка датотека у меком режиму.
$ git ls-files demo dummyfile file1.txt file2.txt file3.txt newfile
Гит Реверт
У Гиту, команда реверт се користи за извођење операције враћања, тј. за враћање неких промена. Слично је команди за ресетовање, али једина разлика је у томе што изводите ново урезивање да бисте се вратили на одређено урезивање. Укратко, поштено је рећи да је команда гит реверт урезивање.
Гит реверт команда не брише никакве податке током извршавања операције враћања.
Рецимо да додајем 3 датотеке и изводим гит операцију урезивања за пример враћања.
$ git commit -m 'add 3 files again' [master 812335d] add 3 files again 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txt
Дневник ће показати ново урезивање.
$ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Сада бих желео да се вратим на једно од мојих прошлих урезивања, рецимо – „59ц86ц9 ново урезивање“. Покренуо бих наредбу испод.
$ git revert 59c86c9
Ово ће отворити датотеку, наћи ћете детаље урезивања на које покушавате да се вратите, и можете да дате име новом урезовању, а затим сачувате и затворите датотеку.
Revert "new commit" This reverts commit 59c86c96a82589bad5ecba7668ad38aa684ab323. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch master # Your branch is ahead of 'origin/master' by 4 commits. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: dummyfile
Након што сачувате и затворите датотеку, ово је излаз који ћете добити.
$ git revert 59c86c9 [master af72b7a] Revert "new commit" 1 file changed, 1 insertion(+), 1 deletion(-)
Сада да извршите неопходне промене, за разлику од ресетовања, реверт је извршио још једно ново урезивање. Ако поново проверите дневник, наћи ћете ново урезивање због операције враћања.
$ git log --oneline af72b7a (HEAD -> master) Revert "new commit" 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Гит дневник ће имати сву историју урезивања. Ако желите да уклоните урезивање из историје, онда враћање није добар избор, али ако желите да задржите промене урезивања у историји, онда је реверт одговарајућа команда уместо ресетовања.
Гит Ребасе
У Гиту, ребасе је начин премештања или комбиновања урезивања једне гране преко друге гране. Као програмер, не бих креирао своје карактеристике на главној грани у стварном сценарију. Радио бих на својој грани („ограничена грана“), а када имам неколико урезивања у својој грани са додатом функцијом, онда бих желео да је преместим у главну грану.
Ребасе понекад може бити мало збуњујуће за разумевање јер је веома слично спајању. Циљ спајања и поновног базирања оба је да узмем урезивање из моје гране функција и ставим их на главну грану или било коју другу грану. Узмите у обзир, имам графикон који изгледа овако:
Претпоставимо да радите у тиму са другим програмерима. У том случају, можете замислити да би ово могло постати веома сложено када имате гомилу других програмера који раде на различитим гранама функција, а они спајају више промена. Постаје збуњујуће за праћење.
Дакле, овде ће ребасе помоћи. Овог пута, уместо да радим гит мерге, урадићу ребасе, где желим да узмем своја два урезивања гране функција и преместим их на главну грану. Ребасе ће узети све моје урезивање из гране функције и преместити их на врх урезивања главне гране. Дакле, иза сцене, гит дуплира урезивање гране карактеристика на главној грани.
Овај приступ ће вам дати чист праволинијски графикон са свим урезивањем у низу.
Олакшава праћење где су урезивања отишла. Можете замислити да ако сте у тиму са много програмера, сва урезивања су и даље у низу. Дакле, заиста је лако пратити чак и ако имате много људи који раде на истом пројекту у исто време.
Дозволите ми да вам ово практично покажем.
Овако тренутно изгледа моја главна грана. Има 4 урезивања.
$ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Покренућу наредбу испод да креирам и пребацим се на нову грану која се зове функција, а ова грана ће бити креирана од 2. урезивања, тј. 59ц86ц9
(master) $ git checkout -b feature 59c86c9 Switched to a new branch 'feature'
Ако проверите дневник у грани функција, он има само 2 урезивања која долазе од мастера (главне линије).
(feature) $ git log --oneline 59c86c9 (HEAD -> feature) new commit e2f44fc (origin/master, origin/HEAD) test
Направићу функцију 1 и урезати је у грану функције.
(feature) $ vi feature1.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 1' [feature c639e1b] feature 1 1 file changed, 1 insertion(+) create mode 100644 feature1.txt
Направићу још једну функцију, тј. функцију 2, у грани карактеристика и урезати је.
(feature) $ vi feature2.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 2' [feature 0f4db49] feature 2 1 file changed, 1 insertion(+) create mode 100644 feature2.txt
Сада, ако проверите дневник гране карактеристика, има два нова урезивања, које сам извршио изнад.
(feature) $ git log --oneline 0f4db49 (HEAD -> feature) feature 2 c639e1b feature 1 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
Сада желим да додам ове две нове функције у главну грану. За то ћу користити команду ребасе. Из гране карактеристика, пребазираћу у односу на главну грану. Оно што ће ово учинити је да ће поново усидрити моју грану карактеристика у односу на најновије промене.
(feature) $ git rebase master Successfully rebased and updated refs/heads/feature.
Сада ћу ићи напред и проверити главну грану.
(feature) $ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits)
И на крају, поново поставите главну грану у односу на моју грану карактеристика. Ово ће узети та два нова урезивања на мојој грани функција и поново их репродуковати на врху моје главне гране.
(master) $ git rebase feature Successfully rebased and updated refs/heads/master.
Сада ако проверим дневник на главној грани, могу да видим да су два урезивања моје гране функција успешно додата у моју главну грану.
(master) $ git log --oneline 766c996 (HEAD -> master, feature) feature 2 c036a11 feature 1 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test
То је било све о ресетовању, враћању и поновном базовању команди у Гиту.
Закључак
То је било све о ресетовању, враћању и поновном базовању команди у Гиту. Надам се да је овај водич корак по корак био од помоћи. Сада знате како да се играте са својим урезивањем према потреби користећи команде поменуте у чланку.