diff --git a/dev.txt b/dev.txt new file mode 100644 index 0000000..04204c7 --- /dev/null +++ b/dev.txt @@ -0,0 +1 @@ +config diff --git "a/git-markdone/\320\270\320\275\321\201\321\202\321\200\321\203\320\272\321\206\320\270\321\217 \320\277\320\276 \321\200\320\260\320\261\320\276\321\202\320\265 \321\201 \321\203\320\264\320\260\320\273\321\221\320\275\320\275\321\213\320\274\320\270 \321\200\320\265\320\277\320\276\320\267\320\270\321\202\320\276\321\200\320\270\321\217\320\274\320\270" "b/git-markdone/\320\270\320\275\321\201\321\202\321\200\321\203\320\272\321\206\320\270\321\217 \320\277\320\276 \321\200\320\260\320\261\320\276\321\202\320\265 \321\201 \321\203\320\264\320\260\320\273\321\221\320\275\320\275\321\213\320\274\320\270 \321\200\320\265\320\277\320\276\320\267\320\270\321\202\320\276\321\200\320\270\321\217\320\274\320\270" new file mode 100644 index 0000000..9394b9b --- /dev/null +++ "b/git-markdone/\320\270\320\275\321\201\321\202\321\200\321\203\320\272\321\206\320\270\321\217 \320\277\320\276 \321\200\320\260\320\261\320\276\321\202\320\265 \321\201 \321\203\320\264\320\260\320\273\321\221\320\275\320\275\321\213\320\274\320\270 \321\200\320\265\320\277\320\276\320\267\320\270\321\202\320\276\321\200\320\270\321\217\320\274\320\270" @@ -0,0 +1,50 @@ +# Работа с удалёнными репозиториями +Чтобы иметь возможность совместной работы над каким-либо Git-проектом, необходимо знать как управлять удалёнными репозиториями. Удалённые репозитории — это модификации проекта, которые хранятся в интернете или ещё где-то в сети. Их может быть несколько, каждый из которых как правило доступен для вас либо только на чтение, либо на чтение и запись. Совместная работа включает в себя управление удалёнными репозиториями и помещение (push) и получение (pull) данных в и из них тогда, когда нужно обменяться результатами работы. Управление удалёнными репозиториями включает умение добавлять удалённые репозитории, удалять те из них, которые больше не действуют, умение управлять различными удалёнными ветками и определять их как ослеживаемые (tracked) или нет и прочее. Данный раздел охватывает все перечисленные навыки по управлению удалёнными репозиториями. +Отображение удалённых репозиториев +Чтобы просмотреть какие удалённые серверы у вас уже настроены, следует выполнить команду git remote. Она перечисляет список имён-сокращений для всех уже указанных удалённых дескрипторов. Если вы склонировали ваш репозиторий, у вас должен отобразиться по крайней мере origin — это имя по умолчанию, которое Git присваивает серверу, с которого вы склонировали: + + $ git clone git://github.com/schacon/ticgit.git Initialized empty Git repository in /private/tmp/ticgit/.git/ remote: Counting objects: 595, done. remote: Compressing objects: 100% (269/269), done. remote: Total 595 (delta 255), reused 589 (delta 253) Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done. Resolving deltas: 100% (255/255), done. $ cd ticgit $ git remote origin Чтобы посмотреть какому URL соответствует сокращённое именя в Git, можно указать команде опцию -v: $ git remote -v origin git://github.com/schacon/ticgit.git Если у вас больше одного удалённого репозитория, команда покажет их все. Например, мой репозиторий Grit выглядит следующим образом. $ cd grit $ git remote -v bakkdoor git://github.com/bakkdoor/grit.git cho45 git://github.com/cho45/grit.git defunkt git://github.com/defunkt/grit.git koke git://github.com/koke/grit.git origin git@github.com:mojombo/grit.git Это означает, что мы легко можем получить изменения от любого из этих пользователей. Но, заметьте, что origin — это единственный удалённый сервер прописанный как SSH ссылка, поэтому он единственный, в который я могу помещать свои изменения (это будет рассмотрено в Главе Git на сервере). + +## Добавление удалённых репозиториев +В предыдущих разделах мы упомянули и немного продемонстрировали добавление удалённых репозиториев, сейчас мы рассмотрим это более детально. Чтобы добавить новый удалённый Git-репозиторий под именем-сокращением, к которому будет проще обращаться, выполните + + git remote add [сокращение] [url]: + $ git remote origin $ git remote add pb git://github.com/paulboone/ticgit.git + $ git remote -v origin git://github.com/schacon/ticgit.git pb git://github.com/paulboone/ticgit.git + +Теперь вы можете использовать в командной строке имя pb вместо полного URL. Например, если вы хотите извлечь (fetch) всю информацию, которая есть в репозитории Павла, но нет в вашем, вы можете выполнить + + git fetch pb: + $ git fetch pb remote: + Counting objects: 58, done. + remote: Compressing objects: 100% (41/41), done. + remote: Total 44 (delta 24), reused 1 (delta 0) Unpacking objects: 100% (44/44), done. + From git://github.com/paulboone/ticgit * [new branch] master -> pb/master * [new branch] ticgit -> pb/ticgit + + Ветка master Павла теперь доступна локально как pb/master. Вы можете слить (merge) её в одну из ваших веток, или теперь вы можете перейти на эту ветку если вы хотите её просмотреть. + +## Fetch и Pull +Как вы только что узнали, для получения данных из удалённых проектов, следует выполнить: + + $ git fetch [remote-name] + +Данная команда связывается с указанным удалённым проектом и забирает все те данные проекта, которых у вас ещё нет. После того как вы выполнили команду, у вас должны появиться ссылки на все ветки из этого удалённого проекта. Теперь эти ветки в любой момент могут быть просмотрены или слиты. + В Главе Git на сервере мы перейдём к более детальному рассмотрению, что такое ветки и как их использовать. Когда вы клонируете репозиторий, команда clone автоматически добавляет этот удалённый репозиторий под именем origin. Таким образом git fetch origin извлекает все наработки, отправленные (push) на этот сервер после того, как вы склонировали его (или получили изменения с помощью fetch). +Важно отметить, что команда fetch забирает данные в ваш локальный репозиторий, но не сливает их с какими-либо вашими наработками, и не модифицирует то, над чем вы работаете в данный момент. Вам необходимо вручную слить эти данные с вашими, когда вы будете готовы. Если у вас есть ветка настроенная на отслеживание удалённой ветки (для дополнительной информации смотри следующий раздел и Главу Ветвление в Git), то вы можете использовать команду git pull. Она автоматичеси извлекает и затем сливает данные из удалённой ветки в вашу текущую ветку. Этот способ может для вас оказаться более простым или более удобным. К тому же по умолчанию команда git clone автоматически настраивает вашу локальную ветку master на отслеживание удалённой ветки master на сервере, с которого вы клонировали (подразумевается, что на удалённом сервере есть ветка master). Выполнение git pull как правило извлекает (fetch) данные с сервера, с которого вы изначально склонировали, и автоматически пытается слить (merge) их с кодом, над которым вы в данный момент работаете. +Push +Когда ваш проект достигает момента, когда вы хотите поделиться наработками, вам необходимо отправить (push) их в главный репозиторий. Команда для этого действия простая: git push [удал. сервер] [ветка]. Чтобы отправить вашу ветку master на сервер origin (повторимся, что клонирование как правило настраивает оба этих имени автоматически), вы можете выполнить следующую команду для отправки наработок обратно на сервер: $ git push origin master Эта команда срабатывает только в случае, если вы клонировали с сервера, на котором у вас есть права на запись, и если никто другой с тех пор не выполнял команду push. Если вы и кто-то ещё одновременно клонируете, затем он выполняет команду push, а затем команду push выполняете вы, то ваш push точно будет отклонён. Вам придётся сначала вытянуть (pull) их изменения и объединить с вашими. Только после этого вам будет позволено выполнить push. Смотри Главу Ветвление в Git для более подробного описания как отправлять (push) данные на удалённый сервер. +Инспекция удалённого репозитория +Если хотите получить побольше информации об одном из удалённых репозиториев, вы можете использовать команду git remote show [удал. сервер]. Если вы выполните эту команду с некоторым именем, например, origin, вы получите что-то подобное: + + $ git remote show origin * remote origin URL: git://github.com/schacon/ticgit.git Remote branch merged with 'git pull' while on branch master master Tracked remote branches master ticgit +Она выдаёт URL удалённого репозитория, а также информацию об отслеживаемых ветках. Эта команда любезно сообщает вам, что, если вы находясь на ветке master, выполните git pull, ветка master с удалённого сервера будет автоматически влита в вашу сразу после получения всех необходимых данных. Она также выдаёт список всех полученных ею ссылок. Это был пример для простой ситуации, и наверняка вы встретились с чем-то подобным. Однако, если вы используете Git более интенсивно, вы можете увидеть гораздо большее количество информации от git remote show: + + $ git remote show origin * remote origin URL: git@github.com:defunkt/github.git Remote branch merged with 'git pull' while on branch issues issues Remote branch merged with 'git pull' while on branch master master New remote branches (next fetch will store in remotes/origin) caching Stale tracking branches (use 'git remote prune') libwalker walker2 Tracked remote branches acl apiv2 dashboard2 issues master postgres Local branch pushed with 'git push' master:master +Данная команда показывает какая именно локальная ветка будет отправлена на удалённый сервер по умолчанию при выполнении git push. Она также показывает каких веток с удалённого сервера у вас ещё нет, какие ветки всё ещё есть у вас, но уже удалены на сервере. И для нескольких веток показано какие удалённые ветки будут в них влиты при выполнении git pull. +## Удаление и переименование удалённых репозиториев +Для переименования ссылок в новых версиях Git можно вылолнить git remote rename, это изменит сокращённое имя, используемое для удалённого репозитория. Например, если вы хотите переименовать pb в paul, вы можете сделать это следующим образом: + + $ git remote rename pb paul $ git remote origin paul +Стоит упомянуть, что это также меняет для вас имена удалённых веток. То, к чему вы обращались как pb/master, стало paul/master. Если по какой-то причине вы хотите удалить ссылку (вы сменили сервер или больше не используете определённое зеркало, или, возможно, контрибьютор перестал быть активным), вы можете использовать + + git remote rm: $ git remote rm paul $ git remote origin Pro Git \ No newline at end of file diff --git a/git_and_problem.md b/git_and_problem.md new file mode 100644 index 0000000..88d64f6 --- /dev/null +++ b/git_and_problem.md @@ -0,0 +1,88 @@ +## Обнаружение ошибок с помощью Git +Git предоставляет несколько инструментов, которые помогут вам найти и устранить проблемы в ваших проектах. Так как Git рассчитан на работу с проектом почти любого типа, эти инструменты имеют довольно обобщённые возможности, но часто они могут помочь вам отловить ошибку или её виновника. + +### Аннотация файла +Если вы обнаружили ошибку в вашем коде и хотите знать, когда она была добавлена и почему, то в большинстве случаев аннотация файла будет лучшим инструментом для этого. С помощью неё для любого файла можно увидеть, каким коммитом последний раз изменяли каждую из строк. Поэтому если вы видите, что некоторый метод в вашем коде работает неправильно, вы можете с помощью команды git blame снабдить файл аннотацией, и таким образом увидеть, когда каждая строка метода была изменена последний раз и кем. + +В следующем примере используется git blame, чтобы определить, какой коммит и коммиттер отвечал за строки в Makefile ядра Linux верхнего уровня и, кроме того, использует параметр -L для ограничения вывода аннотации строками с 69 по 82 из этого файла: + + $ git blame -L 69,82 Makefile + b8b0618cf6fab (Cheng Renquan 2009-05-26 16:03:07 +0800 69) ifeq ("$(origin V)", "command line") + b8b0618cf6fab (Cheng Renquan 2009-05-26 16:03:07 +0800 70) KBUILD_VERBOSE = $(V) + ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) endif + ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) ifndef KBUILD_VERBOSE + ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) KBUILD_VERBOSE = 0 + ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) endif + ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75) + 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 76) ifeq ($(KBUILD_VERBOSE),1) + 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 77) quiet = + 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 78) Q = + 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 79) else + 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 80) quiet=quiet_ + 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 81) Q = @ + 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 82) endif + + +Обратите внимание, что первое поле — это неполная SHA-1 сумма последнего коммита, который изменял соответствующую строку. Следующими двумя полями являются значения, извлечённые из этого коммита — имя автора и время создания коммита — таким образом, вы можете легко увидеть кто изменял строку и когда. После этого следуют номер строки и содержимое файла. Обратите внимание на строки со значением ^4832fe2 в поле коммита, так обозначаются те строки, которые были в первом коммите этого файла. Этот коммит был сделан, когда данный файл был впервые добавлен в проект и с тех пор эти строки не были изменены. Немного сбивает с толку то, что вы уже видели в Git, по крайней мере, три различных варианта использования символа ^ для изменения SHA-1 коммита, в данном случае этот символ имеет такое значение. + +Другая отличная вещь в Git — это то, что он не отслеживает явно переименования файлов (пользователю не нужно явно указывать какой файл в какой был переименован). Он сохраняет снимки и уже после выполнения самого переименования неявно попытается выяснить, что было переименовано. Одна из интересных возможностей, вытекающих из этого — это то, что вы также можете попросить Git выявить перемещения кода всех других видов. Если передать опцию -C команде git blame, Git проанализирует аннотируемый файл и пытается выяснить откуда изначально появились фрагменты кода, если они, конечно же, были откуда-то скопированы. Например, предположим при реорганизации кода в файле GITServerHandler.m вы разнесли его по нескольким файлам, один из которых GITPackUpload.m. Вызывая git blame с опцией -C для файла GITPackUpload.m, вы можете увидеть откуда изначально появились разные фрагменты этого файла. + + $ git blame -C -L 141,153 GITPackUpload.m + f344f58d GITServerHandler.m (Scott 2009-01-04 141) + f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) + gatherObjectShasFromC + f344f58d GITServerHandler.m (Scott 2009-01-04 143) { + 70befddd GITServerHandler.m (Scott 2009-03-22 144) //NSLog(@"GATHER COMMI + ad11ac80 GITPackUpload.m (Scott 2009-03-24 145) + ad11ac80 GITPackUpload.m (Scott 2009-03-24 146) NSString *parentSha; + ad11ac80 GITPackUpload.m (Scott 2009-03-24 147) GITCommit *commit = [g + ad11ac80 GITPackUpload.m (Scott 2009-03-24 148) + ad11ac80 GITPackUpload.m (Scott 2009-03-24 149) //NSLog(@"GATHER COMMI + ad11ac80 GITPackUpload.m (Scott 2009-03-24 150) + 56ef2caf GITServerHandler.m (Scott 2009-01-05 151) if(commit) { + 56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb + 56ef2caf GITServerHandler.m (Scott 2009-01-05 153) + +Это, действительно, полезно. Обычно вы получаете в качестве изначального коммит, в котором вы скопировали код, так как это первый коммит, в котором вы обращаетесь к этим строкам в этом файле. Но в данном случае Git сообщает вам первый коммит, в котором эти строки были написаны, даже если это было сделано в другом файле. + +# Бинарный поиск +Аннотирование файла помогает, если вы знаете, где находится проблема и можете начать исследование с этого места. Если вы не знаете, что сломано, а с тех пор как код работал, были сделаны десятки или сотни коммитов, вы вероятно воспользуетесь командой git bisect. Эта команда выполняет бинарный поиск по истории коммитов для того, чтобы помочь вам как можно быстрее определить коммит, который создал проблему. + +Допустим, вы только что развернули некоторую версию вашего кода в боевом окружении и теперь получаете отчёты о некоторой ошибке, которая не возникала в вашем разработческом окружении, и вы не можете представить, почему код ведет себя так. Вы возвращаетесь к вашему коду и выясняете, что можете воспроизвести проблему, но всё ещё не понимаете, что работает неверно. Вы можете воспользоваться бинарным поиском, чтобы выяснить это. Во-первых, выполните команду git bisect start для запуска процесса поиска, а затем используйте git bisect bad, чтобы сообщить Git, что текущий коммит сломан. Затем, используя git bisect good [good_commit], вы должны указать, когда было последнее известное рабочее состояние: + + $ git bisect start + $ git bisect bad + $ git bisect good v1.0 + Bisecting: 6 revisions left to test after this + [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] Error handling on repo + +Git выяснил, что произошло около 12 коммитов между коммитом, который вы отметили как последний хороший коммит (v1.0), и текущим плохим коммитом, и выгрузил вам один из середины. В этот момент вы можете запустить ваши тесты, чтобы проверить присутствует ли проблема в этом коммите. Если это так, значит она была внесена до выгруженного промежуточного коммита, если нет, значит проблема была внесена после этого коммита. Пусть в данном коммите проблема не проявляется, вы сообщаете об этом Git с помощью git bisect good и продолжаете ваше путешествие: + + $ git bisect good + Bisecting: 3 revisions left to test after this + [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] Secure this thing +Теперь вы оказались на другом коммите, расположенном посредине между только что протестированным и плохим коммитами. Вы снова выполняете ваши тесты, обнаруживаете, что текущий коммит сломан, и сообщаете об этом Git с помощью команды git bisect bad: + + $ git bisect bad + Bisecting: 1 revisions left to test after this + [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] Drop exceptions table +Этот коммит хороший и теперь Git имеет всю необходимую информацию для определения того, где была внесена ошибка. Он сообщает вам SHA-1 первого плохого коммита и отображает некоторую информацию о коммите и файлах, которые были изменены в этом коммите, так, чтобы вы смогли разобраться что же случилось, что могло привнести эту ошибку: + + $ git bisect good + b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit + commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 + Author: PJ Hyett + Date: Tue Jan 27 14:48:32 2009 -0800 + + Secure this thing + + :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 + f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config +Когда вы закончили бинарный поиск, нужно выполнить git bisect reset для того, чтобы вернуть HEAD туда, где он был до начала поиска, иначе вы останетесь в, довольно, причудливом состоянии: + + $ git bisect reset +Это мощный инструмент, который помогает вам за считанные минуты проверить сотни коммитов на возможность внесения ошибки. В действительности, если у вас есть скрипт, который будет возвращать 0 если проект находится в рабочем состоянии и любое другое число в обратном случае, то вы можете полностью автоматизировать git bisect. Сперва, вы снова сообщаете границы бинарного поиска, указывая известные плохие и хорошие коммиты. Вы можете сделать это, передавая их команде bisect start — первым аргументом известный плохой коммит, а вторым известный хороший коммит: + + $ git bisect start HEAD v1.0 + $ git bisect run test-error.sh +Это приведёт к автоматическом выполнению test-error.sh на каждый выгруженный коммит до тех пор, пока Git не найдёт первый сломанный коммит. Вы также можете использовать что-то вроде make или make tests, или что-то ещё, что у вас есть для запуска автоматизированных тестов. \ No newline at end of file