Как я использую git на работе

внешний интерфейс Git
Как я использую git на работе

Это 103-я оригинальная статья без воды.Если вы хотите получить больше оригинальных статей, выполните поиск в общедоступном аккаунте и подпишитесь на нас~ Эта статья была впервые опубликована в блоге Zhengcaiyun:Как я использую git на работе

奕承.png

image

предисловие

Недавно в интернете появился довольно популярный кейс о новом сотруднике, который не умеет тянуть код с Git, и его уволили на следующий день. Из этого видно, что важность Git для нашей работы, будь то фронтенд или бэкенд, неотделима от Git. Давайте выясним.

Приведенный выше случай вызывает вопрос: после прихода в новую компанию, как вы настраиваете локальную среду Git и загружаете код после того, как ваш руководитель назначит вам права доступа к репозиторию? Не паникуйте, выполните четыре шага, которые я собираюсь описать ниже, чтобы убедиться, что вы можете использовать Git для плавного извлечения кода!

  1. Скачать Гитссылка на скачивание, выберите версию, соответствующую вашей системе для загрузки.

  2. Сгенерируйте ssh-ключ на своем компьютере, откройте терминал, выполнитеssh-keygen -t rsa -C "你公司内部邮箱地址", если выполнение прошло успешно, переключиться на~/.sshВ каталоге каталог должен быть следующим. копироватьid_rsa.pubСодержание.

    image-20210519163921819.png

  3. Здесь мы берем Github в качестве примера, как показано на рисунке ниже, введитеsettings -> SSH and GPG keysпройти черезcatкоманда для просмотра файловid_rsa.pub, затем скопируйте его, нажмитеadd ssh key, этот шаг эквивалентен размещению открытого ключа на Github для хостинга.

    image-20210519164643069.png

  4. Глобальная настройка имени пользователя и электронной почты Git

git config --global user.name "xxx"
git config --global user.email "xxx@xx.com"

Выполнив указанные выше четыре шага, вы можете с радостью приступить к разработке кода. В отличие от метода https pull, метод https требует ручного ввода имени пользователя и пароля перед каждой отправкой.После настройки метода ssh Git будет использовать ваш локальный закрытый ключ и открытый ключ удаленного хранилища, чтобы проверить, является ли это пару секретов.ключ, что упрощает процесс работы.

Введение в Git

Прежде чем представить связанные операции Git, я думаю, что очень важно понять происхождение Git и проблемы, для решения которых используется Git. Git (произносится как /gɪt/) — это распределенная система управления версиями с открытым исходным кодом, которая может эффективно и с высокой скоростью управлять версиями небольших и очень крупных проектов. Линус Торвальдс, я думаю, все знают этого человека, изобретателя системы Linux с открытым исходным кодом. Сегодня большинство серверов, которые вы видите, на самом деле работают на системах Linux.Удивительно, что этот программист уровня бога не только создал системы Linux. Как управляется код Linux? До 2002 года добровольцы по всему миру отправляли Линусу файлы исходного кода с помощью diff, а затем Линус сам сливал код вручную! Вы должны знать, что объем кода в Linux в то время был уже очень большим, из-за ручного управления один был подвержен ошибкам, а другой имел низкую эффективность. Итак, Линус выбрал коммерческую систему управления версиями BitKeeper. Владелец BitKeeper, BitMover, разрешил Linux-сообществу бесплатно использовать эту систему управления версиями из гуманитарного духа. Наконец, по какой-то причине компания BitMover вернула права на бесплатное использование сообщества Linux, поэтому Линус потратил две недели на самостоятельное написание распределенной системы управления версиями на C, которая является источником Git.

img

Рабочая область и процесс Git

Чтобы понять, как Git управляет нашим кодом, первое, что нужно сделать, — понять, как устроена рабочая область Git. Потому что, только если вы досконально понимаете состав рабочей области Git, вы можете использовать соответствующую команду в соответствующей области. Как показано на рисунке ниже, этот рисунок содержит 4 рабочих области Git и некоторые общие операции.

git

Рабочая область: рабочая область — это место, где обычно выполняются разработка и внесение изменений. Это самый последний контент, который в данный момент просматривается. Процесс разработки также является работой рабочей области.

Индекс: промежуточная область при выполненииgit addПосле команды файлы в рабочей области будут перемещены в промежуточную область.Промежуточная область помечает содержимое текущей рабочей области, которой управляет Git.Когда необходимо отправить определенное требование или функцию, первым шагом является передачаgit addСначала отправьте на плацдарм.

Репозиторий: Локальный склад, расположенный на вашем компьютере, черезgit commitОтправьте содержимое промежуточной области, оно попадет на локальный склад.

Удаленный: удаленный склад, сервер, используемый для размещения кода.Содержимое удаленного хранилища может быть изменено локальным хранилищем в отношениях сотрудничества, распределенных в нескольких местах.После того, как локальный склад изменил код, он может быть переданgit pushКоманда для синхронизации кода с удаленным репозиторием.

Вообще говоря, рабочий процесс Git делится на следующие этапы.

1.在工作区开发,添加,修改文件。
2.将修改后的文件放入暂存区。
3.将暂存区域的文件提交到本地仓库。
4.将本地仓库的修改推送到远程仓库。

Основные операции Git

git add

Добавьте файлы в промежуточную область

# 添加某个文件到暂存区,后面可以跟多个文件,以空格区分
git add xxx
# 添加当前更改的所有文件到暂存区。
git add .

git commit

# 提交暂存的更改,会新开编辑器进行编辑
git commit 
# 提交暂存的更改,并记录下备注
git commit -m "you message"
# 等同于 git add . && git commit -m
git commit -am
# 对最近一次的提交的信息进行修改,此操作会修改commit的hash值
git commit --amend

git pull

# 从远程仓库拉取代码并合并到本地,可简写为 git pull 等同于 git fetch && git merge 
git pull <远程主机名> <远程分支名>:<本地分支名>
# 使用rebase的模式进行合并
git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

git fetch

а такжеgit pullразница в томgit fetchОперация только извлекает удаленные изменения и не выполняет операцию слияния автоматически. Не влияет на ваш текущий код

# 获取远程仓库特定分支的更新
git fetch <远程主机名> <分支名>
# 获取远程仓库所有分支的更新
git fetch --all

git branch

# 新建本地分支,但不切换
git branch <branch-name> 
# 查看本地分支
git branch
# 查看远程分支
git branch -r
# 查看本地和远程分支
git branch -a
# 删除本地分支
git branch -D <branch-nane>
# 重新命名分支
git branch -m <old-branch-name> <new-branch-name>

Сценарии решения проблем с помощью Git на работе

git rebase делает ваши коммиты более читабельными

Использование git rebase

Rebase транслируется в rebase, и его функция очень похожа на слияние, которое используется для слияния модификаций ветки с текущей веткой.

Как показано на рисунке ниже, следующий рисунок описывает изменения в истории коммитов после перебазирования.

WechatIMG2.png

Теперь давайте воспользуемся примером, чтобы объяснить описанный выше процесс.

Предположим, что теперь у нас есть 2 ветки, одна главная, а другая feature/1.Все они проверены ветки на основе первоначальной отправки add readme.После этого в ветке master добавляются файлы 3.js и 4.js соответственно. . 2 отправки, а feature/1 также добавляет файлы 1.js и 2.js, соответствующие следующим 2 записям отправки соответственно.

На данный момент запись фиксации соответствующей ветки выглядит следующим образом.

Мастер-филиал, как показано ниже:

image-20210531144909187.png

Особенность / 1 ветвь следующим образом

image-20210531145504071.png

В сборе это выглядит так

image-20210531145553107.png

В этот момент переключитесь на ветку feature/1 и выполнитеgit rebase master, после успеха, поgit logПросмотр записей.

Как показано на рисунке ниже: вы можете видеть, что изменения ветки master применяются одно за другим, а затем каждое изменение feature/1 применяется одно за другим, используя последний коммит ветки master в качестве базовой точки.

image-20210531150719965.png

Поэтому наша запись коммита будет очень четкой и не будет форков.Выше показана относительно гладкая ситуация, но в большинстве случаев в процессе перебазирования будут возникать конфликты.В этом случае нам нужно вручную разрешать конфликты, и затем используйте по очередиgit add ,git rebase --continue способ справиться с конфликтами и завершить процесс перебазирования, если вам не нужен результат перебазирования, вам нужно использоватьgit rebase --skip чтобы пропустить эту операцию перебазирования.

Разница между git merge и git rebase

отличный отgit rebaseда,git mergeВ случае не перемотки вперед (быстрого слияния) будет сгенерирована дополнительная запись слияния, аналогичнаяMerge branch 'xxx' into 'xxx'сообщение фиксации.

image-20210531151838328.png

Кроме того, при разрешении конфликтов нужно разрешить только один конфликт слиянием, что просто и грубо, а при использовании rebase нужно разрешать каждый конфликт по очереди перед коммитом.

git rebase интерактивный режим

В разработке часто встречается, что на ветке генерируется много невалидных коммитов, в этом случае с помощью интерактивного режима rebase можно сжать несколько произошедших коммитов в один коммит и получить чистую историю коммитов, например , история фиксации ветки выглядит следующим образом:

image-20210518211345258.png

Чтобы войти в интерактивный режим, выполните:

git rebase -i <base-commit>

параметрbase-commitЭто объект фиксации, который указывает базовую точку операции, и операция перебазирования выполняется на основе этой базовой точки.Для приведенного выше примера истории фиксации нам нужно сжать фиксацию перед последним объектом фиксации ( ac18084 ) в один commit Формат команды, который нам нужно выполнить, следующий:

git rebase -i ac18084

На этом этапе вы перейдете на интерактивную страницу vim, и редактор отобразит информацию следующим образом.

image-20210518212036198.png

Чтобы объединить эту кучу изменений, нам нужно использовать стратегию слияния Squash, то есть слияние текущего коммита с его предыдущим содержимым коммита, что можно примерно выразить следующим образом, в интерактивном режиме rebase, по крайней мере, один пик сохраняется, иначе команда не будет выполнена.

pick  ... ...
s     ... ... 
s     ... ... 
s     ... ... 

После изменения файла нажмите:потомwqСохраните и выйдите, и появится другая страница редактирования.Эта страница используется для редактирования представленной информации и изменения ее дляfeat: 更正, наконец, сохраните его, а затем используйтеgit branchПроверьте отправленную информацию о коммите. Запись коммита после перебазирования показана на рисунке ниже. Операция rebase может сделать нашу историю коммитов более понятной.

image-20210518212812000.png

В частности, вы можете перебазировать только ту ветку функций, которую используете, а перебазировать ветку интеграции нельзя, потому что эта операция изменит историю ветки интеграции.

Используйте git cherry-pick, чтобы получить указанный коммит

git cherry-pickЭто можно понимать как «выбор» коммитов.В отличие от слияния, которое объединяет все коммиты ветки, он берет один коммит ветки и вводит его в вашу текущую ветку как новый коммит. Когда нам нужно объединить коммиты других веток локально, если мы не хотим объединять всю ветку, а просто хотим объединить коммит в текущую локальную ветку, тогда нам нужно использоватьgit cherry-pick.

В следующем сценарии ниже есть три ветви: feature/cherry-pick1 и feature/cherry-pick2 — это две функциональные ветви, основанные на основной проверке, и соответствующие записи журнала ветвей выглядят следующим образом.

image-20210518221001432.png

image-20210518221010458.png

Коммиты в основной ветке следующие:image-20210518221051734.png

Теперь мастеру нужны только изменения, связанные с feature/cherry-pick1 и feature/cherry-pick2, и ему не нужны изменения, связанные с содержимым исправления. На этом этапе вы можете использовать команду cherry-pick.

грамматика:git cherry-pick [commit-hash]

commit-hash представляет собой хеш-значение коммита. Теперь последовательно выполните следующие две инструкции.git cherry-pick e0bb7f3,git cherry-pick c9a3101, в процессе, если есть конфликт, после разрешения конфликтаgit add , затем выполнитеgit cherry-pick --continue, и, наконец, коммит на master выглядит следующим образом

image-20210518235707190.png

На этом этапе необходимые коммиты применяются к ветке master, и желаемый эффект достигается. Если вам нужно несколько вариантов вишни, которые необходимо синхронизировать с целевой веткой, это можно сократить какgit cherry-pick <first-commit-id>...<last-commit-id>, который представляет собой интервал, который открывается слева и закрывается справа, что означает, чтоfirst-commit-idИзменения кода, внесенные фиксацией, не будут объединены в прошлом.Если вам нужно объединить прошлое, вы можете использоватьgit cherry-pick <first-commit-id>^...<last-commit-id>, что означает, что содержитfirst-commit-idприбытьlast-commit-idКоммиты внутри будут объединены.

Используйте git revert для отката коммита

Представьте такой сценарий, у вашего проекта есть 2 версии, которые недавно вышли в сеть, и эти две версии также сопровождаются исправлениями ошибок, оставленных ранее.В начале вы исправляли ошибки на релизной ветке первой версии, Внезапно накануне релиза тестировщик сообщил что исправления ошибок в первой версии нужно менять на вторую версию.В это время в представлении ветки интеграции первой версии должна быть первая версия.Определенно не возможно грубо удалить предыдущие коммиты по исправлению ошибок с помощью сброса.В то же время такой подход более опасен.На данный момент мы не хотим уничтожать Что мне делать,если я хочу отозвать запись о фиксации ошибки,которую мы оставили позади в предыдущей записи коммита? git revert пригодится.

git revertОтзыв конкретной операции, это действие не изменяет представление исходной записи, но отправит новую запись для компенсации конкретной операции.

грамматика:git revert <commit-id>Для обычных коммитов

git revert <commit-id> -mкоммит для слияния

Давайте использовать случай, чтобы понять эту команду.Как показано на рисунке ниже, предположим, что место, обведенное красной рамкой, является отправкой, которая вызовет ошибку.После его отправки было сделано 2 отправки, включая заявки других коллег. .

image-20210519142702752.png

На данный момент я хочу убить ошибку, которая вызвала отправку и выполнитьgit revert 1121932, после выполнения операции откройте журнал просмотра, как показано на рисунке ниже, вы можете видеть, что добавлена ​​новая запись коммита.Сообщение, сгенерированное этим коммитом, генерируется автоматически, начиная с Revert, за которым следует отозванный коммит- msg.Запись коммита никуда не делась, а эффект отката кода в это время тоже достигнут.

image-20210519142824836.png

Кроме того, git revert также может откатить несколько коммитов.

грамматика:git revert [commit-id1] [commit-id2] ...Обратите внимание, что это интервал вперед-открытие-назад-закрытие, то есть исключая commit1, но включая commit2.

Есть два способа откатить наши коммиты, один из которых упоминался выше.git revertВ дополнение к команде вы также можете использоватьgit resetкоманда, так какая между ними разница?

git revertБудет создано новое сообщение фиксации для отмены предыдущих изменений.

git resetЗапись фиксации будет возвращена непосредственно в указанную фиксацию.

Для ветвей личных функций вы можете использоватьgit resetдля перехода назад и вперед по истории, затем используйтеgit push --forceОтправьте на удаленный сервер, но если он находится в интегрированной ветке, где сотрудничают несколько человек, не рекомендуется использовать его напрямую.git resetкоманду, используйте более безопасныйgit revertкоманда для отмены фиксации. Таким образом, история коммитов не будет стерта и может быть безопасно отозвана.

Постановка файлов с помощью git stash

Будет сценарий, в котором вы сейчас разрабатываете новые функции в своей функциональной ветке. На данный момент в продакшене есть ошибка, которую нужно срочно исправить, но вы не закончили разработку этой части кода и не хотите ее отправлять, что делать? Можно использовать в это времяgit stashКоманда сначала временно сохраняет измененные файлы в рабочей области, а затем переключается на ветку исправлений, чтобы исправить ошибку.После завершения исправления переключитесь обратно на ветку функций, чтобы восстановить содержимое, только что сохраненное из стека.

Основные команды следующие

git stash //把本地的改动暂存起来
git stash save "message" 执行存储时,添加备注,方便查找。
git stash pop // 应用最近一次暂存的修改,并删除暂存的记录
git stash apply  // 应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即 stash@{0},如果要使用其他个,git stash apply stash@{$num} 。
git stash list // 查看 stash 有哪些存储
git stash clear // 删除所有缓存的 stash

Давайте узнаем больше о командах тайника через несколько картинок.

На данный момент я работаю над новой функцией, которая изменяет содержимое файла 1.js.

image-20210519175036869.png

Разработка не завершена.В данный момент я хочу перейти на ветку хотфиксов для исправления ошибки.Приходится приостанавливать разработку и переходить на ветку хотфиксов,но в рабочей области еще есть контент.На данный момент, если я переключу ветку, Git сообщит о следующей ошибке

error: Your local changes to the following files would be overwritten by checkout:
        1.js
Please commit your changes or stash them before you switch branches.
Aborting

Смысл приведенного выше предложения означает, что в рабочей области есть модификации файлов, которые не могут быть отправлены.Вам необходимо сначала выполнить операцию фиксации или сохранения, а затем выполнитьgit stash, результат следующий

Saved working directory and index state WIP on stash: 22e561c feat: add 1.js

На данный момент наше рабочее пространство очищено, и мы можем переключиться на ветку исправлений для исправления ошибок. Предположим, мы завершили исправление ошибок и продолжаем переключаться обратно на ветку функций для разработки исходной функции. В настоящее время мы только нужно выполнитьgit stash pop, временно сохраненные нами изменения будут восстановлены в рабочей области, как показано на следующем рисунке.

image-20210519185011012.png

Когда мы хотим создавать файлы и переключать ветки, чтобы что-то делать, мы можем использоватьgit stashЭтот механизм способствует развитию.

При использовании команд, связанных с тайником, рекомендуется не использовать его напрямую каждый раз, когда вы временно сохраняете его.git stashКоманда, проходящая вниз, но использованиеgit stash save "message..."Таким образом, делается информационная запись для данного представления. Таким образом, когда вы хотите применить изменения, сначала пройдитеgit stash listВзгляните на все промежуточные списки. После этого рекомендуется использоватьgit stash apply stash@${num}Таким образом, применяется соответствующий тайник, так что существующие элементы списка тайников не будут очищены, и его можно будет применить к текущему рабочему пространству.Если вам не нужно это временное хранилище, вы можете очистить его вручную.

Отменить изменения в разных рабочих областях

В разработке нам часто нужно откатить работу кода, в разных областях работы способ отката кода тоже разный. Как показано на рисунке ниже, если вы сейчас разрабатываете ветвь feature/revoke,

сначала черезgit statusПроверьте текущий статус.

image-20210520115802579.png

В настоящее время наше рабочее пространство очень чистое без каких-либо операций по модификации. В это время измените код и снова проверьте статус. Вы можете видеть, что файл 1.js был изменен.

image-20210520115934693.png

Теперь мы хотим восстановить файл 1.js в состояние до модификации, то есть для снятия модификации рабочей области мы можем использоватьgit checkout -- <filename>Если вы хотите отозвать модификацию нескольких файлов, разделите файлы пробелами.Как показано на рисунке ниже, мы отозвали модификацию файла 1.js, и рабочая область была восстановлена.

image-20210520120242475.png

Если мы изменили файл сейчас и отправили его в промежуточную область, если нам не нужна эта часть файла, то мы можем передатьgit reset <filename>команда для отмены определенного файла,git resetВсе файлы в области временного хранения будут отозваны, как показано на рисунке ниже.Проверив состояние до и после, можно увидеть, что файлы наконец-то успешно выведены в рабочую область.

image-20210520141538130.png

Настройте псевдоним git для повышения эффективности работы

Как правило, на работе, после получения задачи на разработку, нам нужно создать новую ветку для разработки, в это время нам нужно использоватьgit branch,git checkout,git pullЖдем команды, после того как покушаем, разработка завершена, а когда дело доходит до стадии сдачи кода и так далееgit add,git commit,git pushКоманды ожидания хотя и просты, но недостаточно кратки для ввода.Как программисты, мы разрабатываем программы для повышения нашей эффективности.Лень является источником человеческого прогресса, поэтому мы можем упростить эти команды, настроив псевдонимы.

Его основное использованиеgit config --global alias.<简化的字符> 原始命令

Например, следующий пример:

$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch

Здесь co означает проверку, ci означает фиксацию, br означает ветвь, а фиксацию можно сократить как

image-20210519152804390.png

--globalЭто глобальный параметр, то есть после его однократной настройки эти команды можно применять ко всем складам под этим компьютером. Эти команды фактически обновляют ваш глобальный файл .gitconfig, который используется для сохранения глобальной конфигурации git,vim ~/.gitconfig, после выполнения этой команды дисплей выглядит следующим образом, на следующем рисунке показаноgit config --global aliasДополнительныйalias.

image-20210519153624712.png

В дополнение к описанному выше способу прямой передачи команды вы также можете изменитьaliasпункт для установки псевдонима.

Здесь я делюсь общей настройкой псевдонима, которую использую, и заменяю следующую конфигурацию той, что находится в файле .gitconfig.[alias]Область, которой он принадлежит, и тогда вы можете использовать его с радостью~

[alias]
st = status -sb
co = checkout
br = branch
mg = merge
ci = commit
ds = diff --staged
dt = difftool
mt = mergetool
last = log -1 HEAD
latest = for-each-ref --sort=-committerdate --format=\"%(committername)@%(refname:short) [%(committerdate:short)] %(contents)\"
ls = log --pretty=format:\"%C(yellow)%h %C(blue)%ad %C(red)%d %C(reset)%s %C(green)[%cn]\" --decorate --date=short
hist = log --pretty=format:\"%C(yellow)%h %C(red)%d %C(reset)%s %C(green)[%an] %C(blue)%ad\" --topo-order --graph --date=short
type = cat-file -t
dump = cat-file -p
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

Таким образом, каждый раз, когда мы хотим просмотреть историю Git, нам не нужно напрямую вводить такую ​​длинную серию команд.git lg, на следующем рисунке показана запись отправки в исходном коде axios с использованием упакованногоgit lgПросмотренные рендеры

image-20210519162327693.png

Отношения между ветвями ясны с первого взгляда, и операция слияния, выполняемая для каждой фиксации, также ясна, что может помочь нам отслеживать исторические фиксации и решать проблемы.

Суммировать

В этой статье объясняется построение среды Git, базовое использование и использование команд Git, которые чаще всего используются в работе. Независимо от того, разрабатываете ли вы интерфейс, серверную часть или что-то еще, использование Git незаменимо в повседневной работе. Не только уметь пользоваться, но и красиво пользоваться, гибко пользоваться, стабильно пользоваться. Таким образом, вы можете быть более удобными при совместной работе над проектами с коллегами.Изучив навыки использования Git в этой статье, вы сможете много практиковаться в своей повседневной работе, и я верю, что это принесет вам большие плоды!

использованная литература

Руководство по git от Ruan Yifeng

Разница между командами слияния веток Git и rebase

Рекомендуемое чтение

Процесс выполнения v8 js

Практика с вами, чтобы начать работу с плагином Webpack

работы с открытым исходным кодом

  • Zhengcaiyun интерфейсный таблоид

адрес с открытым исходным кодомwww.zoo.team/openweekly/(На главной странице официального сайта таблоида есть группа обмена WeChat)

Карьера

ZooTeam, молодая, увлеченная и творческая команда, связанная с отделом исследований и разработок продукции Zhengcaiyun, базируется в живописном Ханчжоу. В настоящее время в команде более 40 фронтенд-партнеров, средний возраст которых составляет 27 лет, и почти 30% из них — инженеры полного стека, настоящая молодежная штурмовая группа. В состав членов входят «ветераны» солдат из Ali и NetEase, а также первокурсники из Чжэцзянского университета, Университета науки и технологий Китая, Университета Хандянь и других школ. В дополнение к ежедневным деловым связям, команда также проводит технические исследования и фактические боевые действия в области системы материалов, инженерной платформы, строительной платформы, производительности, облачных приложений, анализа и визуализации данных, а также продвигает и внедряет ряд внутренних технологий. Откройте для себя новые горизонты передовых технологических систем.

Если вы хотите измениться, вас забрасывают вещами, и вы надеетесь начать их бросать; если вы хотите измениться, вам сказали, что вам нужно больше идей, но вы не можете сломать игру; если вы хотите изменить , у вас есть возможность добиться этого результата, но вы не нужны; если вы хотите изменить то, чего хотите достичь, вам нужна команда для поддержки, но вам некуда вести людей; если вы хотите изменить установившийся ритм, это будет "5 лет рабочего времени и 3 года стажа работы"; если вы хотите изменить исходный Понимание хорошее, но всегда есть размытие того слоя оконной бумаги.. , Если вы верите в силу веры, верьте, что обычные люди могут достичь необыкновенных вещей, и верьте, что они могут встретить лучшего себя. Если вы хотите участвовать в процессе становления бизнеса и лично способствовать росту фронтенд-команды с глубоким пониманием бизнеса, надежной технической системой, технологиями, создающими ценность, и побочным влиянием, я думаю, что мы должны говорить. В любое время, ожидая, пока вы что-нибудь напишете, отправьте это наZooTeam@cai-inc.com