Category Archives: develop

develop

Git Basics: branch cleanup

通常我们的项目都是创建分支开发来做功能迭代,随着项目的开发周期延长功能的不断迭代,git 远程库里会出现大量的分支。
理想状态下,当我们开发完一个功能后提交测试的时候,在处理 Merge Request 时,git merge 业务分支,同时勾选删除源开发分支 Delete source-branch,这样可以防止过多无用的 git 分支。这里记录一下如何手动清理分支:

Delete a branch both locally and remotely

To remove a local branch from your machine:

git branch -d <branch_name>

NOTE: If using -d (lowercase d), the branch will only be deleted if it has been merged. To force the delete to happen, you will need to use -D (uppercase D).

To remove a remote branch:

git push origin :<branch_name>

Thought : wasn’t a good indicator for [delete], As of Git 1.7.0, use this alternative syntax to delete remote branches:

git push origin --delete <branch_name>

[Tips]: if you want to complete both these steps with a single command, you can make an alias for it by adding the below to your ~/.gitconfig:

[alias]
  rmbranch = "!f(){ git branch -d ${1} && git push origin --delete ${1}; };f"

Alternatively, you can add this to your global config from the command line using

git config --global alias.rmbranch '!f(){ git branch -d ${1} && git push origin --delete ${1}; };f'

Sync local refs with remote repository

git remote prune <upstream>

will remove any remote refs you have locally that have been removed from your remote.

Also can fetch and prune with git fetch -p | --prune or git remote update [upstream] -p

The -p argument prunes deleted upstream branches. Thus, if the foo branch is deleted in the origin repository, git remote update -p will automatically delete your origin/foo ref.

Cleanup branches already merged

To delete local branches which have already been merged into master:

git checkout dev
git fetch -p # sync remote to local, also cleanup branches that have already been deleted
git branch --merged master |grep -v "\* master" |xargs -n 1 git branch -d

Note: For above command, if omit the master branch argument, we will get local branches which have already been merged into the current HEAD.

Now we need remove all remote branches have already been merged into dev:

git branch -r --merged origin/dev |grep -v '\*\|master\|dev' |sed 's#\s*origin/##' |xargs -n 1 echo

Make sure these branches are expected, And then remove from remote by replacing the echo with git push origin --delete

Another syntax to cleanup:

git push origin $(git branch -r --merged origin/master | sed "s/origin\\//:/" | egrep -v "HEAD|master|dev")

Note: Please make sure you known what these command to do before you execute it.

Now we can easily write a bash script (or ruby, or whatever) that goes through (maybe as a cron job) and deletes merged branches.

Reference Links

http://stevenharman.net/git-clean-delete-already-merged-branches

Nodejs memory leak detector

Just wrote a simple module to tracking down memory leaks.

Create a standalone module

cat menoryUsageInfo.js

/**
 * Memoryusage info detections.
 * @author Allex Wang (allex.wxn@gmail.com)
 */
module.exports = function() {
  // output memory usage info every 2 minutes
  var min = 0, last = 0, interval = 2 * 1000
  var pid = process.pid
  process.nextTick(function f() {
    var o = process.memoryUsage()
    var percent = ~~((o.heapUsed / o.heapTotal) * 100) + '%'
    if (!min || o.heapUsed < last) {
      min = o.heapUsed
      console.warn([pid, (min / 1048576) + 'M' + '/' + (o.heapTotal / 1048576) + 'M', percent])
    }
    last = o.heapUsed
    setTimeout(f, interval)
  })
}

Create a simple web server for memory leak detections

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(7070, '127.0.0.1');

console.log('Server running at http://127.0.0.1:7070/. Process PID: ', process.pid);

require('./menoryUsageInfo')();

If we hit this continuously with

while true; do curl -s http://127.0.0.1:7070/; done

in one shell, and in another shell view our process: top -pid <process pid> we will see very high and erratic memory usage for this node process.

For more details about memory detections there are two awesome node modules – memwatch and heapdump.

Reference Urls

VIM skills

Merge multiple blank lines

:%s/^\_s\+\n/\r/g

Note: \_s match white space and blank lines

Grep by unicode character

# replace back slash(\) to front slash(/)
:%s#\%x5C#/#g

:help regexp for details about some specific syntax to select unicode characters with a regular expression in Vim.

|/\%d|  \%d \%d match specified decimal character (eg \%d123)
|/\%x|  \%x \%x match specified hex character (eg \%x2a)
|/\%o|  \%o \%o match specified octal character (eg \%o040)
|/\%u|  \%u \%u match specified multibyte character (eg \%u20ac)
|/\%U|  \%U \%U match specified large multibyte character (eg \%U12345678)

Maven deploy and release

The “SNAPSHOT” term means that the build is a snapshot of your code at a given time.

It usually means that the version is a version still under heavy development.

When it comes time to release your code, you will want to change the version listed in the pom. So instead of having a “1.0.0-SNAPSHOT” you would have something like “1.0.0″.

If your project.version contains SNAPSHOT (f.e., 1.2-SNAPSHOT) and you execute mvn deploy, artifacts will be deployed to your snapshot repository. If it doesn’t (f.e., 1.2) – they will be deployed to your release repository.

Maven 项目管理的时候,日常发布版本,我们都是直接 mvn deploy 到一个 SNAPSHOT 版本,那如何发布 stable 版本呢?

本篇描述了,如何使用 mvn 命令对一个项目进行从 1.0.0-SNAPSHOT 版本升级到 1.0.0,同时在 scm 中进行打 tag 后,修改版本到 1.0.1-SNAPSHOT,同时 commit 到 branch。

#1. 添加 scm 和 plugin 定义

<scm>
  <developerConnection>scm:git:git@git.n.xiaomi.com:allex/yp-assist.git</developerConnection>
</scm>
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-release-plugin</artifactId>
  <version>2.5</version>
  <!--
  <configuration>
    <tagBase>https://code.miliao.com/repos/xiaomi-miliao/tags/src/cloud/yp-assist/</tagBase>
  </configuration>
  -->
</plugin>

为了保障 svn 目录清洁,建议在使用 svn 作为 scm 时,添加上面注释的段落,git 项目不用加

#2. release:prepare 准备工作

$ mvn release:prepare
  • 忽略 SNAPSHOT 依赖,强制发布,mvn release:prepare -DignoreSnapshots=true – 和 -DskipTest=true 一样令人讨厌,不建议使用
  • 此操作会向 git/svn 写入内容
  • 新手建议:-DdryRun=true 此命令加 dryRun 是演习,不会向 git/svn checkin 任何内容。-DdryRun=true 可用 mvn release:clean 回滚。
  • 会检查各个版本是否是 SNAPSHOT,会在运行中要求你回答使用什么版本。
  • 准备工作的作用:加版本 & checkin + 打 tag 到 git/svn 中

#3. 发包工作

$ mvn release:perform
  • 这一步,会去一个临时目录中,把 commit 的代码抓出来 build 之后 deploy。

#4. 清理工作

$ mvn release:clean

References Pages:

Git recover from git reset –hard

How to recover uncommitted changes to the working directory from a

git reset --hard HEAD?

You can try git fsck --lost-found to see if your changes still in lost-found:

$ git fsck --lost-found
Checking object directories: 100% (256/256), done.
Checking objects: 100% (54/54), done.
dangling blob 15f9af8379f13672ca0e75d56df100edfd67fe6b
dangling commit 18fc9548f20eb8938dde68ab4a3dd0b7a0212dc3
dangling commit 33a832866e3855e300504ea6b584732e9c3c286c
dangling blob 568ca393d5e21cdc9eda2824111a5429a70d5113
dangling blob 89cdac4d3fc03546b5ab485aa8a9905b34702a4a
dangling blob abf03d6c84484a2b096a4d7f0ee5a85361f8a3d6 <- it's this one
dangling commit bc05be5eac21134b63ca51fbd20fee5c8782a640
dangling commit c0fa59cfaa0bad5f8ca8a1a845ba1673bb207b2d
dangling commit d140d6f693d8ef83d040d483bec3db95db084cd9
dangling blob e9c3eb31aa0589ab59f46630f7926681f7a14476  <- it's this one

Then you will get a dangling blob by git show

git show e9c3eb31aa0589ab59f46630f7926681f7a14476

will give you the file content back of reset.

To find unreferenced commits I found a tip somewhere suggesting this.

gitk --all $(git log -g --pretty=format:%h)

I found them in the other directory within the <path to repo>/.git/lost-found/. From there, I can see the uncommitted files, copy out the blobs, and rename them.

Note: This only works if you added the files you want to save to the index (using git add .). If the files weren’t in the index, they are lost.

How to get url hash state safely

Normally, we can get the hash string by location.hash. But currently i fond the value is not actually correct in FF. FF automatically decoding encoded hash string in the URL.

So safely method is avoid use location.hash, and it is better to use location.href.split('#')[1] instead of location.hash.

Indeed location.href.split('#!')[1] does not get decoded by FF automatically (at least today).

var currentUrl = '';
var getHashPath = function() { 
    return location.href.split('#!')[1];
};
$(window).on('hashchange', function(e) {
    var url = getHashPath();
    if (url !== currentUrl) {
        currentUrl = url;
        // do some business logic...
    }
});

MySQL DBA commonds

Create user and grand privileges;

mysql> create user wp_blog_usr@localhost identified by '123qwe';
Query OK, 0 rows affected (0.05 sec)

mysql> grant all privileges on wp_blog.* to wp_blog_usr@'localhost';
Query OK, 0 rows affected (0.02 sec)

mysql> flush privileges;

By default in MySQL server remote access is disabled. To provide a remote access to user is:

  1. comment this line in /etc/my.cnf:
    # bind-address = 127.0.0.1

  2. grant pivileges for user:
    GRANT ALL PRIVILEGES ON *.* TO 'USERNAME'@'IP' IDENTIFIED BY 'PASSWORD';
    Where IP is the IP you want to allow acess and USERNAME is the user you use to connect If you want to allow access from any IP just put % instead of your IP

  3. restart mysql server

To tell the server to reload the grant tables, perform a flush-privileges operation. This can be done by issuing a FLUSH PRIVILEGES statement or by executing a mysqladmin flush-privileges or mysqladmin reload command.

Change root password

mysqladmin -u root password 123qwe;

See full query from show processlist

show full processlist;

So how many processes or connections are now actually doing anything? We now must check for ‘Threads_running’.

mysql> SHOW GLOBAL STATUS LIKE 'Threads_running';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| Threads_running | 24    |
+-----------------+-------+
1 row in set (0.00 sec)

And so we have Threads_cached, Threads_connected & Max_used_connections.

Reset Forgotten MySQL Root Password

# start up the mysql daemon and skip the grant tables which store the passwords.
mysql_safe --skip-grant-tables &

# connect to mysql without a password.
mysql --user=root mysql

# update password
UPDATE user SET password=PASSWORD('new-password') WHERE user='root';
flush privileges;
exit;

Some related links:

MySQL terminology: processes, threads & connections

maven pom.xml settings

Adding main class to manifest

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.4</version>
  <configuration>
    <archive>
      <manifest>
        <mainClass>com.yahoo.platform.yui.compressor.Bootstrap</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

Customize java source directory:

Some project’s source directory is not following the maven convention. Instead of being inside src/main/java

Just add this to your pom in the build section.

<sourceDirectory>
  ${basedir}/src
</sourceDirectory>

Here’s the relevant section of the POM doc on configuring the directories.

Including local JAR files as dependency in a Maven project

To avoid fetch dependency from remote repository is to use Maven’s system scope and systemPath feature:

<dependency>
  <groupId>net.sf</groupId>
  <artifactId>jargs</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>${basedir}/lib/jargs-1.0.jar</systemPath>
</dependency>

This will reference a dependency from the local filesystem, which means you do not have to install the JAR into the repository in order to use it. This is particularly useful when you’re doing some prototyping or research into a new technology.

Skipping Tests

If you want to skip tests by default but want the ability to re-enable tests from the command line, you need to go via a properties section in the pom:

<project>
  [...]
  <properties>
    <skipTests>true</skipTests>
  </properties>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.16</version>
        <configuration>
          <skipTests>${skipTests}</skipTests>
        </configuration>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

This will allow you to run with tests disabled by default and to run them with this command:

mvn install -DskipTests=false

If you absolutely must, you can also use the maven.test.skip property to skip compiling the tests. maven.test.skip is honored by Surefire, Failsafe and the Compiler Plugin.

mvn install -Dmaven.test.skip=true

For details see Skipping Tests

Feedly

The best thing about Feedly is that you can sync it with your Google Reader so any subscriptions you want to hang on to, just transfer them over with one click. This is the frontrunner and most talked about reader that may very well take the place of Google Reader. Why? Because it’s easy to navigate, everything is in a familiar format but with a nice hipster like spin to make it easier on the eyes.

I’ve yet to hear of a downside to using Feedly. As a matter of fact I’ve only heard of one: If the Feedly server is down then you can’t access the reader. How often is that really going to happen though?

It only took me minutes to get up and running with Feedly. I also love their apps, as I tend to consume most of my RSS feeds on my mobile. I’m pretty impressed, and excited to see how Feedly improves once they reach larger audiences.

image0059 637x410 6 Feed Readers to Replace the Google Reader Void