Programação não linear PHP utilizando Git

De artista.frustrado

Tabela de conteúdo

Git

Git é um sistema de controle de versões distribuído (DVCS) criado pelo finlandês Linus Torvalds. Descrito por muitos como o DVCS criado com o intuito de fazer as pessoas sentirem-se menos inteligentes do que realmente são e como "o gerenciador de informação do inferno" por seu criador, Git tem expandido seus recursos assim como sua base de usuários de forma exponecial desde sua criação em 2005.

Assim como a kernel do Linux, a criação do git é marcado por uma determinação de desenvolver a melhor ferramenta com o senso de humor de Linus. Enquanto a base do código do git é levada muito a sério, com objetivos e princípios bem definidos, o ambiente de desenvolvimento é bem humorado. O próprio nome dado ao programa ... Racionalizando sobre o nome, Linus observa:

“Sou um bastardo egoísta e nomeio todos os meus projetos em homenagem a mim mesmo. Primeiro Linux, agora git.”
  • Linux = Híbrido dos nomes Linus e Mimix
  • Git = gíria britânica que descreve uma pessoa idiota ou sem valor.

Sistemas de Controles de Versão

Siglas/Nomenclatura

Siglas para sistemas de controle de versão:

  • VCS – Version Control System
  • SCM – Source Code Manager
  • RCS – Revision Control System


Histórico dos Sistemas de Controle de Versão

História de SCMs:

SCCS – Source Code Control System
  • Criado no Início dos anos 1970 por M.J. Rochkind
  • Início de conceitos ainda pertinentes nos SCMs atuais. ex.: repositório
  • Problema: arquivo de LOCK - enquanto um usuário trabalha outro não tem acesso ao arquivo
RCS – Revision Control System
  • Criado no início dos anos 1980 por Walter Tichy
CVS – Concurrent Version System
  • Criado em 1986 por Dick Grune.
  • Extendeu e modificou o modelo do RCS
  • Altera sistema de lock de forma a permitir que várias pessoas possam trabalhar no mesmo arquivo concorrentemente. Introduzido o conceito de mescla (merge).


SVN – Subversion
  • Criado com o intuito de corrigir as falhas de arquitetura do CVS
  • Introduziu:
    • Commit Atomico
    • Melhor suporte a galhos (branches)
BitKeeper e Mercurial
  • Distanciam-se do modelo dos sistemas anteriores ao eliminar o repositório central.
  • Armazenagem distribuída:
    • cada desenvolvedor possui sua própria cópia completa e compartilhável
    • derivado do modelo P2P (peer-to-peer)
Mercurial e Monotone
  • Utilizam hash para identificar o conteúdo dos arquivos - Influenciou a arquitetura do git.

Git

Kernel do Linux

  • Utilizou tarbals e arquivos de patch.
  • Controvérsia com a utilização do BitKeeper (proprietário)
  • Problema de Licença do BitKeeper - Larry McVoy removeu a licença de utilização do BitKeeper para projetos de código aberto depois de acusar Andrew Tidwell de tentar executar engenharia reversa no BitKeeper.
  • Linus Torvalds faz acordo com McVoy e abandona BitKeeper no desenvolvimento da kernel.
  • Linus analisa SCMs abertos e conclui que nenhum deles respondem à suas necessidades. Entre as opções de voltar a tarballs / patches e criar um SCM próprio opta pela segunda.

Utilizadores do Git

  • Git
  • Linux Kernel
  • Perl
  • Eclipse
  • Gnome
  • KDE
  • Qt
  • Ruby on Rails
  • Android
  • PostgreSQL
  • Debian
  • X.org
  • Zend Framework 2

Objetivos do Git

  • Facilitar desenvolvimento distribuído
  • Escalável – suportar milhares de usuários
  • Execução rápida e eficiente
  • Manter integridade e confiança
  • Obrigar responsabilidades (enforce accountability)
  • Imutabilidade – depois de criados os objetos não podem ser alterados.
  • Transações atômicas – alterações diferentes mas relacionadas são executadas como um todo ou não são executadas.
  • Suportar e incentivar desenvolvimento ramificado (Branched Development)
  • Repositórios completos
  • Design interno limpo
  • Livre, “como em liberdade”

Arquitetura

Modelo de Objetos

Baseado em estrutura de sistemas de diretórios.

SHA

Toda informação necessária para representar a história de um projeto é aramazenada em arquivos referenciados plor um nome de objeto de 40 dígitos.

EX:

6ff87c4664981e4397625791c8ea3bbb5f2279a3

Nome dos objetos - hash SHA1 do conteúdo do objeto

Hash SHA1 = função critpográfica

Vantagens de SHA
  • Conflitos de nomenclatura: virtualmente impossível encontrar 2 objetos com o mesmo nome
  • Comparação: a identificação de objetos idênticos é rápida pois só é necessário comparar os nomes
  • Consistencia de nome em vários repositórios: os nomes dos objetos são calculados da mesma forma nos vários repositórios - o mesmo conteúdo armazenado em 2 repositórios terá o mesmo nome
  • Detecção de erros nos objetos: git pode identificar erros na leitura de objetos ao conferir o nome do objeto com o hash SHA1 do seu conteúdo.

Atributos

Tipos:

  • Blob: utilizado para armazenar dados de arquivos - normalmente um arquivo
  • Tree: basicamente como um diretório - referencia outros objetos (trees, blobs) assim como diretórios referenciam subdiretórios e arquivos
  • Commit: aponta para uma árvore marcando seu estado em um determinando momento. Contém meta informações sobre esse momento como: timestamp, autor das alterações desde o último commit, um ponteiro para os commits anteriores, etc.
  • Tag: maneira de marcar commits como sendo especiais. comumente utilizado para marcar commits de uma versão específica do app ou algo neste sentido.

Configuração

arquivo de configuração .git/config

 [core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
 [remote "origin"]
        fetch = +refs/heads/*:refs/remotes/origin/*
        url = usuario@servidor:/caminho/projetox/
 [branch "master"]
        remote = origin
        merge = refs/heads/master

Importante

  • Git: Faz snapshot do estado atual dos arquivos na estrutura de árvores a cada commit.
  • Git gerencia conteúdo, não arquivos.
  • Git percebe quando conteúdo é movido de um arquivo para outro.
  • Arquivos/pastas vazios não são armazenados no repositório.


Progamação Não Linear

  • Desenvolver vários recursos simultaneamente utilizando a mesma base de código mas em galhos separados.
  • Mesclar recursos/alterações quando as mesmas estiverem comprovadamente funcionais.

Ex.

Prog-nao-linear.png

Na figura acima vemos um exemplo clássico de programação não linear. Em um branch master (galho principal no git), são criados galhos para cada recurso/alteração. Quando os mesmos são concluídos e/ou aprovados pelo cliente são mesclados no master, caso contrário são abandonados/apagados.


Instalação Git

Debian/Ubuntu

 sudo apt-get install git-core gitk

Windows

Baixar e instalar MsGit e TortoiseGIT

Eclipse

Configuração

Usuário

git config --global user.name "Fernando Michelotti"
git config --global user.email artista.git@frustrado.com.br

Ambiente

git config --global color.branch auto
git config --global color.diff auto
git config --global color.interactive auto
git config --global color.status auto

Exemplo de Progamação Não Linear

Nada como um bom exemplo prático para facilitar o entendimento de novos conceitos e ferramentas. Por isso iremos utilizar como exemplo um sistema fictício de citações.

Abaixo temos uma especificação super simplificada:

Projeto exemplo:
Sistema de citações.
Descrição dada pelo cliente/chefe:
“Uma paginazinha com citações de pensadores para os visitantes perceberem nossa superioridade intelectual.” (citação direta)
Dados fornecidos pelo cliente:
1 citação: 
Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de falhar. - Bill Gates - The Road Ahead (1995)
Solução proposta:
KISS (Keep It Simple Stupid)
1 página + 1 citação = 1 html estático

Implementação

1a versão

 <html>
 <head>
 </head>
 <body>
 <h1>Pensamento</h1>
 <p>
 Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder. - Bill Gates - The Road Ahead (1995)
 </p>
 </body>
 </html>

Criar repositório:

$ mkdir projeto
$ cd projeto
$ git init
Initialized empty Git repository in /tmp/projeto/.git/
$ vim index.html
$ git add index.html
$ git commit -a -m 'inicio do projeto'
[master (root-commit) a8f0cc2] inicio do projeto
 1 files changed, 10 insertions(+), 0 deletions(-)
 create mode 100644 index.html

Alteração

Mostrar uma de 3 citações aleatoriamente toda vez que a página é acessada.

Criar branch:

$ git checkout -b aleatorio
Switched to a new branch 'aleatorio'
$ git mv index.html index.php
$ vim index.php


<html>
<head>
</head>
<body>
<h1>Pensamento</h1>
<?php
$pensamentos = array();
$pensamentos[] = "Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder. - Bill Gates - The Road Ahead (1995)";
$pensamentos[] = "Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder. - Bill Gates - The Road Ahead (1995)";
$pensamentos[] = "Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder. - Bill Gates - The Road Ahead (1995)";
echo "<p>". $pensamentos[rand(0, count($pensamentos) - 1)] . "</p>\n";
?>
</body>
</html>


Commit:

$ git commit -a
[aleatorio 02a2fb2] Subsituído html estático por escolha aleatória de citações utilizando a função rand em chaves de array
 2 files changed, 16 insertions(+), 10 deletions(-)
 delete mode 100644 index.html
 create mode 100644 index.php
$ git branch
* aleatorio
  master
Mesclar (merge):
$ git checkout master
Switched to branch 'master'
$ git pull . aleatorio
From .
 * branch            aleatorio  -> FETCH_HEAD
Updating a8f0cc2..02a2fb2
Fast-forward
 index.html |   10 ----------
 index.php  |   16 ++++++++++++++++
 2 files changed, 16 insertions(+), 10 deletions(-)
 delete mode 100644 index.html
 create mode 100644 index.php
$ ls
index.php

Refatoração:

$ git checkout -b refatoracao
Switched to a new branch 'refatoracao'
$ vim funcoes.php
<?php
function escolher_citacao()
{
       $pensamentos = array();
        $pensamentos[] = "Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder. - Bill Gates - The Road Ahead (1995)";
        $pensamentos[] = "Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder. - Bill Gates - The Road Ahead (1995)";
        $pensamentos[] = "Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder. - Bill Gates - The Road Ahead (1995)";
        return $pensamentos[rand(0, count($pensamentos) - 1)];
}
$ vim index.php
<html>
<head>
</head>
<body>
<h1>Pensamento</h1>
<?php
include_once "funcoes.php";
echo "<p>". escolher_citacao()."</p>";
?>
</body>
</html>

Refatoração:

$ git add funcoes.php
$ git commit -a
[refatoracao ecd9f1b] Separada lógica da apresentacao atraves da criação de arquivo funcoes.php
 2 files changed, 24 insertions(+), 16 deletions(-)
 create mode 100644 funcoes.php
 rewrite index.php (88%)

Layout:

$ git checkout master
$ git checkout -b layout
$ vim estilo.css
body, td, div, p { font-family: Verdana, Arial, Helvetica, Sans-Serif;  font-size: 11px;}
body { background-color: #EEEEEE; }
$ vim index.php
<head>
<link rel="stylesheet" href="estilo.css" media="screen" />
</head>
$ git add estilo.css
$ git commit -a
[layout ccff6c9] Colocadas instrucoes de layout em arquivo css externo
 2 files changed, 11 insertions(+), 0 deletions(-)
 create mode 100644 estilo.css

Mescla:

$ git pull . layout refatoracao
From .
 * branch            layout     -> FETCH_HEAD
 * branch            refatoracao -> FETCH_HEAD
Fast-forwarding to: ccff6c99f190896c3d37f10bfad4813c85f18204
Trying simple merge with ecd9f1b6e8953bc95c5ab1274a5c19987286e59a
Simple merge did not work, trying automatic merge.
Auto-merging index.php
Merge made by octopus.
 estilo.css  |   10 ++++++++++
 funcoes.php |   12 ++++++++++++
 index.php   |    9 +++------
 3 files changed, 25 insertions(+), 6 deletions(-)
 create mode 100644 estilo.css
 create mode 100644 funcoes.php

Repositórios remotos:

Criando repositório remoto:

$ssh usuario@servidor
$ mkdir projetox
$ cd projetox/
$ git init --bare
Initialized empty Git repository in /tmp/projetox/

Adicionando repositório remoto à lista do repositotio local:

git remote add empresax usuario@servidor:/tmp/projetox/

Histórico

Histórico:

$ git log
commit 12e615323dee6eb9a3548369981a549133291710
Merge: ccff6c9 ecd9f1b
Author: Fernando Michelotti <artista@frustrado.com.br>
Date:   Tue May 31 05:25:52 2011 -0300
 
    Merge branches 'layout' and 'refatoracao'
 
commit ccff6c99f190896c3d37f10bfad4813c85f18204
Author: Fernando Michelotti <artista@frustrado.com.br>
Date:   Tue May 31 05:21:06 2011 -0300
 
    Colocadas instrucoes de layout em arquivo css externo
 
commit ecd9f1b6e8953bc95c5ab1274a5c19987286e59a
Author: Fernando Michelotti <artista@frustrado.com.br>
Date:   Tue May 31 05:04:27 2011 -0300

Repositórios remotos:

Adicionando repositório remoto à lista do repositotio local:

git remote add empresax usuario@servidor:/tmp/projetox/
Exportando branch master para repositório remoto (empresax):
$ git push empresax master
Counting objects: 17, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (17/17), 2.07 KiB, done.
Total 17 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (17/17), done.
To /tmp/projetox/
 * [new branch]      master -> master

Clonando repositório:

$ git clone usuario@servidor:/tmp/projetox/
Cloning into projetox...
Done.
$ cd projetox/
$ vim citacoes.sql
CREATE DATABASE citacao;
USE citacao;
CREATE TABLE IF NOT EXISTS `citacao` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `citacao` text NOT NULL,
  `autor` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
 
INSERT INTO `citacao` (`id`, `citacao`, `autor`) VALUES
(1, 'Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder.', 'Bill Gates - The Road Ahead (1995)'),
(2, 'Sucesso é um péssimo professor. Ele seduz pessoas espertas em pensar que eles são incapazes de perder.', 'Bill Gates - The Road Ahead (1995)');
$ git add citacao.sql
$ git commit -a
[master e973365] adicionado script sql para banco de dados
 1 files changed, 13 insertions(+), 0 deletions(-)
 create mode 100644 citacao.sql
$ git push origin master
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 699 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /tmp/projetox/
   12e6153..e973365  master -> master
$ git rebase origin master
Already on 'master'
Current branch master is up to date.
$ vim funcoes.php
$ git commit -a
[master 023781a] removida array e implementada solucao baseada em banco de dados
 1 files changed, 11 insertions(+), 12 deletions(-)
 rewrite funcoes.php (93%)
$ git push origin master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 503 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /tmp/projetox/
   e973365..023781a  master -> master

Gitk

Gitk.png

Faxina:

$ git branch
  aleatorio
  layout
* master
  refatoracao
$ git branch -d aleatorio
Deleted branch aleatorio (was 02a2fb2).
$ git branch -d layout
Deleted branch layout (was ccff6c9).
$ git branch -d refatoracao
Deleted branch refatoracao (was ecd9f1b).
$ git branch
* master


Tags

$ git log
commit 023781a376765bf37b30e51f5ba67d8103a86c88
Author: Fernando Michelotti <fernando.michelotti@cnt.com.br>
Date:   Tue May 31 06:19:55 2011 -0300
    removida array e implementada solucao baseada em banco de dados
commit e973365a451ab0d7fa842d6e2ae6da7d96f1bca6
Author: Fernando Michelotti <fernando.michelotti@cnt.com.br>
Date:   Tue May 31 06:03:04 2011 -0300
    adicionado script sql para banco de dados
 
$ git tag estavel-1 023781a376765bf37b30e51f5ba67d8103a86c88
$ git tag rc1 12e615323dee6eb9a3548369981a549133291710
$ git tag
estavel-1
rc1

Checkout de versões antigas:

$ git log
commit 023781a376765bf37b30e51f5ba67d8103a86c88
Author: Fernando Michelotti <fernando.michelotti@cnt.com.br>
Date:   Tue May 31 06:19:55 2011 -0300
    removida array e implementada solucao baseada em banco de dados
commit e973365a451ab0d7fa842d6e2ae6da7d96f1bca6
Author: Fernando Michelotti <fernando.michelotti@cnt.com.br>
Date:   Tue May 31 06:03:04 2011 -0300
    adicionado script sql para banco de dados

Checkout de commits antigos:

$ git checkout 12e615323dee6eb9a3548369981a549133291710
Note: checking out '12e615323dee6eb9a3548369981a549133291710'.
 
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
 
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
 
  git checkout -b new_branch_name
 
HEAD is now at 12e6153... Merge branches 'layout' and 'refatoracao'
 
$ git checkout master
Previous HEAD position was 12e6153... Merge branches 'layout' and 'refatoracao'
Switched to branch 'master'

Checkout de uma Tag:

$ git tag
estavel-1
rc1
$ git checkout rc1
Note: checking out 'rc1'.
 
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
 
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
 
  git checkout -b new_branch_name
 
HEAD is now at 12e6153... Merge branches 'layout' and 'refatoracao'