composer create-project 创建已安装依赖、无 Git 历史、可立即运行的新项目;git clone 获取完整源码仓库(含 .git 和全部提交记录),但 vendor 为空,需手动 install 才能运行。

create-project 本质是“开箱即用”,git clone 是“源码全量搬运”
直接说结论:composer create-project 创建的是一个**已安装依赖、无 Git 历史、可立即运行的新项目**;git clone 拿到的是**完整源码仓库(含 .git 目录、所有分支/提交记录)**,但 vendor 通常为空,必须手动 composer install 才能跑起来。
关键差异不在“能不能装上依赖”,而在于:你到底要参与开发,还是只想快速启动一个新应用?
-
git clone https://github.com/laravel/laravel.git my-app→ 得到带.git的完整 Laravel 源码库,但vendor/不存在,composer install后才生成依赖和autoload.php -
composer create-project laravel/laravel my-app→ 不拉 Git 历史,只下载最新稳定版的代码快照 + 自动执行composer install,my-app/下没有.git,是个干净的、独立的新项目起点
为什么 create-project 默认不带 .git 目录?
因为它的设计目标不是“协作开发”,而是“项目初始化”。模板包(如 laravel/laravel)在 Packagist 上发布时,打包的是 dist 归档(tar/zip),不是 Git 仓库本身 —— 所以天然不含 .git。这也是为什么加 --prefer-dist(默认行为)比 --prefer-source 更快、更轻量。
如果你硬要 clone 出来再装依赖,却忘了删掉原项目的 .git,后续 git init 就会出问题:子模块残留、远程 origin 指向原仓库、提交历史污染你的新项目……这些坑都源于混淆了“模板复用”和“源码贡献”两个场景。
- 想给 Laravel 提 PR?→ 用
git clone,然后composer install --no-dev(避免 dev-only 工具干扰) - 想做个新后台系统?→ 用
composer create-project laravel/laravel my-admin,干净利落 - 想基于私有模板初始化?→ 必须确保模板的
composer.json里没写"type": "library"(虽不影响 create-project,但语义错乱易误导)
create-project 背后悄悄干了哪些事?
它不是简单封装 git clone + composer install,而是一套原子化流程:下载归档 → 解压 → 重写 composer.json 中的 name 和 autoload 命名空间(防冲突)→ 运行 post-create-project-cmd 脚本(如有)→ 清理临时文件。
这意味着:即使模板里写了 "scripts": {"post-create-project-cmd": ["php setup.php"]},create-project 也会自动触发它;而 git clone 后手动 composer install 不会触发这个钩子 —— 这是很多自定义模板初始化失败的根本原因。
composer create-project --repository='{"type": "vcs", "url": "https://github.com/myorg/internal-template"}' myorg/internal-template my-project
注意:私有模板必须显式指定 --repository,否则 Composer 会去 Packagist 查找,报错 Could not find package...。
什么时候必须用 git clone?
只有三种真实场景绕不开 git clone:
- 你要 checkout 特定 commit 或旧版本分支(比如调试 Laravel 6.x 的某个 bug),而
create-project只支持语义化版本号(如6.20.0),不支持dev-fix-redis-bug这类分支名 - 你想保留原始提交历史用于审计或追溯(例如合规要求)
- 模板项目未发布到 Packagist,且其
composer.json缺少name字段或格式不规范,导致create-project无法识别为合法包
其他情况,尤其是团队内部脚手架、CI 初始化、新手入门,create-project 是更安全、更可控的选择 —— 它天然规避了因误操作 git pull 导致的本地修改被覆盖、composer.lock 被意外提交等高频事故。










